| Register | FAQ | Calendar | Search | Today's Posts | Mark Forums Read |
|
#1
| |||
| |||
| Please try to suppress your groans :-) but I have a current problem of trying to back-port a program compiled in Turbo Pascal's {$G+} mode, which uses 286 instructions like SHR reg,immed. and ENTER/LEAVE, back to 8086. (The original source is lost so I can't simply recompile it.) I have successfully disassembled the program to a recompilable asm source and fixed all of the SHx/ROx reg,immed. instances but have a few ENTER/LEAVE stack frame commands. I have having trouble figuring out what to do with those. It was my understanding that all ENTER did was something like: push bp mov bp,sp (then the rest of the procedure, like load vars off the stack via [BP +06] etc.) ENTER takes two operands and it looks like the first operand does "SUB SP,operand". Is that right? The second operand however has me completely confused (tasm manual says "gives the lexical nesting level of the routine within the high-level language source code and determines the number of stack frame pointers copied into the new stack frame from the preceeding frame" which has stumped me). I don't think I need to worry about the second operand because they're all 0 which I believe simply pushes BP -- is that right? I guess what I'm asking is help from the experts on how to properly "emulate" ENTER/LEAVE using only 808x opcodes. |
|
#2
| |||
| |||
| On Mon, 11 Aug 2008 00:12:55 -0700 (PDT), Jim Leonard <spamtrap@crayne.org> wrote: >Please try to suppress your groans :-) but I have a current problem of >trying to back-port a program compiled in Turbo Pascal's {$G+} mode, >which uses 286 instructions like SHR reg,immed. and ENTER/LEAVE, back >to 8086. (The original source is lost so I can't simply recompile >it.) I have successfully disassembled the program to a recompilable >asm source and fixed all of the SHx/ROx reg,immed. instances but have >a few ENTER/LEAVE stack frame commands. I have having trouble >figuring out what to do with those. It was my understanding that all >ENTER did was something like: > >push bp >mov bp,sp > >(then the rest of the procedure, like load vars off the stack via [BP >+06] etc.) > >ENTER takes two operands and it looks like the first operand does "SUB >SP,operand". Is that right? The second operand however has me >completely confused (tasm manual says "gives the lexical nesting level >of the routine within the high-level language source code and >determines the number of stack frame pointers copied into the new >stack frame from the preceeding frame" which has stumped me). I don't >think I need to worry about the second operand because they're all 0 >which I believe simply pushes BP -- is that right? > >I guess what I'm asking is help from the experts on how to properly >"emulate" ENTER/LEAVE using only 808x opcodes. I've never used ENTER/LEAVE, but "PC Magazine Programmer's Technical Reference: The Processor and Coprocessor" by Robert L. Hummel gives this pseudocode (for 16-bit operation): level=op2 MOD 32 PUSH BP frame_pointer=SP IF (level>0) THEN FOR j=1 to level-1 BP=BP-2 PUSH [BP] ENDFOR PUSH frame_pointer ENDIF BP=frame_pointer SP=SP-op1 Hope this helps! Bob Masta DAQARTA v4.00 Data AcQuisition And Real-Time Analysis www.daqarta.com Scope, Spectrum, Spectrogram, Sound Level Meter FREE Signal Generator Science with your sound card! |
|
#3
| |||
| |||
| Jim Leonard <spamtrap@crayne.org> wrote in news:c158b61c-5add-4829- 9005-92efe6f15122@p25g2000hsf.googlegroups.com: > a few ENTER/LEAVE stack frame commands. I have having trouble > figuring out what to do with those. It was my understanding that all > ENTER did was something like: > > push bp > mov bp,sp > > (then the rest of the procedure, like load vars off the stack via [BP > +06] etc.) > > ENTER takes two operands and it looks like the first operand does "SUB > SP,operand". Is that right? The second operand however has me > completely confused (tasm manual says "gives the lexical nesting level > of the routine within the high-level language source code and > determines the number of stack frame pointers copied into the new > stack frame from the preceeding frame" which has stumped me). I don't > think I need to worry about the second operand because they're all 0 > which I believe simply pushes BP -- is that right? > > I guess what I'm asking is help from the experts on how to properly > "emulate" ENTER/LEAVE using only 808x opcodes. You should download the IA-32 software developer's manual from Intel's web site. Volume 2 is the instruction reference and has a detailed description (including pseudo-code) for each instruction. As long as the second argument is always 0, then you can replace "enter N, 0" with: push bp mov bp, sp sub sp, N Volume 1 of the manual has a chapter describing how enter and leave are used in the implementation of "Procedure Calls for Block-Structured Languages". GH |
|
#4
| |||
| |||
| On Aug 11, 7:14 am, Gil Hamilton <spamt...@crayne.org> wrote: > You should download the IA-32 software developer's manual from Intel's > web site. Volume 2 is the instruction reference and has a detailed > description (including pseudo-code) for each instruction. As long as > the second argument is always 0, then you can replace "enter N, 0" with: > push bp > mov bp, sp > sub sp, N > > Volume 1 of the manual has a chapter describing how enter and leave are > used in the implementation of "Procedure Calls for Block-Structured > Languages". Thanks to Bob and Gil for the explanation/references/advice! I've downloaded the IA-32 reference (head-smacking moment there, not realizing Intel's own docs were free) and am going over it now. |
|
#5
| |||
| |||
| (Just in case this repeats, Google said I hadn't signed on...!) Aaagh! It's all about how you use the stack for aguments. If the original program actually pushed the segment and offsets onto the stack before calling the subroutine, then the subroutine just saves the BP register on the stack (after the parameters and return address) and usese it to find, address and copy the addresses of the parameters directly. as shown below and as needed. Prior to exiting, the subroutine recovers the BP register contents then returns, specifying how many words to pop off the stack. Here there are 5 parameters so we POP 5*4 = 20 additional words during the return and the hardware also pops off the return address. (This 16-bit code writes a string on screen with/without colour at YX based on MODE) OUTS proc far ;CALL OUTS(MODE,PG-ATTR,YX,L,STRING); PUSH BP ;save BP MOV BP,SP ;access to stack PUSH BP ;save because will use BP as well .... LES BX,dword ptr [bp+22] MOV AX,ES:[BX] ;AX=MODE ..... LES BX,dword ptr [bp+10] MOV CX,ES:[BX] ;CX=COUNT (L) .... .... MOV ES:[BX],DX ;store new YX : MOV SP,BP POP BP ;SAVED BP RET 20 END and so on. However, another method was to have the address of the parameters put directly after the call instruction, and the subroutine knew the return adddress was on the stack, but the addresses of the parameters were those calculated from the return address, and the real return address is then modified to be AFTER the parameters, but so giving access to those parameters. This kind of routine will have lots of arithmetic on the stack pointer contents The first example I showed is the "standard calling convention" of Microsoft (if there is any such thing). And is/was the standard MS Fortran calling convention implementation too |
|
#6
| |||
| |||
| "Terence" <spamtrap@crayne.org> ha scritto nel messaggio news:5ee78d5a-11fb-4856-af91-3439d4df6c84@v13g2000pro.googlegroups.com... > (Just in case this repeats, Google said I hadn't signed on...!) Aaagh! > > It's all about how you use the stack for aguments. i until now not understan why have to function: PUSH BP ;save BP MOV BP,SP ;access to stack and use ebp for memory can be access by esp why not have: /* 0ebp,4edi,8esi,12ebx,16ra, 20P1, 24P2, 28P3+ 1024 function: push ebx push esi push edi push ebp sub esp, 1024 %define variabile1 0 %define variabile2 4 %define array 80 mov eax, [esp + 20 +1024] ; first parameter lea eax, [esp+Array] ; point to 944 array in esp %undef array %undef variabile2 %undef variabile1 lea esp, [esp +1024] pop ebp pop edi pop esi pop ebx ret and use ebp like other registers note that in this way is possible the access of old ebx, esi, ebp eg. mov eax, [esp+1024+8] should access the old esi don't know if it is right... |
|
#7
| |||
| |||
| rio wrote: > i until now not understan why have to > > function: > PUSH BP ;save BP > MOV BP,SP ;access to stack > > and use ebp for memory can be access by esp > Because my example is for segmented 16-bit ASM. not flat-memory model 32-bit ASM. With 16-bit ASM the registers are more or less fixed in their use and have specific names which makes an examplel easier to understand. And in the example, one of the parameters is a string, which has to be addressed with the Byte Pointer (BP) register, so THAT TOO, had to be saved and popped. .. |
|
#8
| |||
| |||
| "rio" <spamtrap@crayne.org> wrote in news:48a123d3$0$18157 $4fafbaef@reader3.news.tin.it: > "Terence" <spamtrap@crayne.org> ha scritto nel messaggio > news:5ee78d5a-11fb-4856-af91-3439d4df6c84@v13g2000pro.googlegroups.com... >> It's all about how you use the stack for aguments. > > i until now not understan why have to > > function: > PUSH BP ;save BP > MOV BP,SP ;access to stack > > and use ebp for memory can be access by esp You can do so with the 386 and beyond. However, with 286 and previous processors, SP (there was no ESP) couldn't be used as a base register, nor could most of the other registers. Only BX and BP could be used as base registers. With the 386, in addition to extending the registers to 32 bits, the restrictions on register usage were greatly relaxed. If you look at the output of a recent x86 gcc compiler, for example, you'll find that it does quite often generate stack references using the ESP register. GH |
|
#9
| |||
| |||
| Gil Hamilton wrote: > > PUSH BP ;save BP > > MOV BP,SP ;access to stack > You can do so with the 386 and beyond. However, with 286 and previous > processors, SP (there was no ESP) couldn't be used as a base register, nor > could most of the other registers. Only BX and BP could be used as base > registers. I agree as long as the comment refers to the use of SP. "You can do this" seems to be intended to refer to SP-2 in the original OP question. But the above code works for 286 because SP is not used as a base register, but BP and BX were. SP is only saved and the contents transferred. By using 16-bit ASM (and only 16 bit registers) one can write programs that still work for real DOS from 286 up and under DOS emulators from Windows 3.1 up and in Macintosh. |
|
#10
| |||
| |||
| Terence wrote: > > By using 16-bit ASM (and only 16 bit registers) one can write programs > that still work for real DOS from 286 up and under DOS emulators from > Windows 3.1 up and in Macintosh. > You can do it in C too, and you can also write programs that work from the 8086 up... -hpa |
![]() |
| Thread Tools | |
| Display Modes | |
In an effort to better serve ads to our visitors, cookies are used on objectmix.com. For more information, check out our Privacy Policy.