Page 1 of 1

variable call address in ASM

Posted: Sun Jun 17, 2007 10:53 pm
by kubeos
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.

Posted: Mon Jun 18, 2007 1:45 am
by AJ
Hi,

I believe that the problem is that you are trying to mix an immediate value and a register. Try using 2 pointers.

Cheers,
Adam

Posted: Mon Jun 18, 2007 4:09 am
by XCHG
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:

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
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.

Posted: Mon Jun 18, 2007 9:57 am
by kubeos
Thanks XCHG,

That was exactly what I needed to know.