Hi,
I've never needed to do this until now, but I can't figure it out.
How can I do a call in real mode like this:
mov ax,0x2000
mov ds,ax
mov es,ax
call 0x2000:(variable) <--- nasm won't let me use a reg here or di or si
Thanks.
variable call address in ASM
When the CALL instruction (assuming FAR CALL) is issued, these things will happen:
1) The CALL instruction will push the segment of the next instruction into the stack.
2) The CALL instruction will push the (E)IP of the next instruction into the stack.
3) The CALL instruction will push the segment of the destination address into the stack.
4) The CALL instruction will push the (E)IP of the destination address into the stack.
5) The CALL instruction will act just like the RETF instruction.
So, CALL is basically an advanced RET(F/N). Now that you have a variable offset into a segment that you want to call, just do as I told you above: push the CS:IP of the instruction that you want to return to after your call, push the CS:IP of the destination address that you want to call and then issue the RETF instruction. Here is an example that I have written in TASM. It must give you the idea of how CALL can be simulated with RET:
The [WriteFar] procedure is a FAR procedure that needs a string to print as a far parameter. Now look at how values are pushed onto the stack before the @@EP return point.
Hope that helps.
1) The CALL instruction will push the segment of the next instruction into the stack.
2) The CALL instruction will push the (E)IP of the next instruction into the stack.
3) The CALL instruction will push the segment of the destination address into the stack.
4) The CALL instruction will push the (E)IP of the destination address into the stack.
5) The CALL instruction will act just like the RETF instruction.
So, CALL is basically an advanced RET(F/N). Now that you have a variable offset into a segment that you want to call, just do as I told you above: push the CS:IP of the instruction that you want to return to after your call, push the CS:IP of the destination address that you want to call and then issue the RETF instruction. Here is an example that I have written in TASM. It must give you the idea of how CALL can be simulated with RET:
Code: Select all
; ------------------------------
WriteFar PROC FAR
; far void WriteFar (far const char* String); StdCall;
PUSH AX
PUSH BX
PUSH BP
MOV BP , SP
; [BP + 06h] = Return point's segment
; [BP + 08h] = Return point's offset
; [BP + 0Ah] = String to print
MOV BX , WORD PTR [BP + 0Ah]
MOV AH , 0Eh
@@WriteFarLoop:
MOV AL , BYTE PTR [BX]
TEST AL , AL
JZ @@WriteFarEP
DW 10CDh
INC BX
JMP @@WriteFarLoop
@@WriteFarEP:
POP BP
POP BX
POP AX
RETF 04h
WriteFar ENDP
; ------------------------------
EVEN
START:
ASSUME DS:@DATA, CS:@CODE, SS:@STACK
MOV AX , @DATA
MOV DS , AX
PUSH OFFSET String1
PUSH SEG @@EP
PUSH OFFSET @@EP
PUSH SEG WriteFar
PUSH OFFSET WriteFar
RETF
@@EP:
MOV AX , 4C00h
DW 21CDh
END START
Hope that helps.
On the field with sword and shield amidst the din of dying of men's wails. War is waged and the battle will rage until only the righteous prevails.