variable call address in ASM

Programming, for all ages and all languages.
Post Reply
kubeos
Member
Member
Posts: 138
Joined: Tue Jan 30, 2007 2:31 pm
Location: Kamloops BC, CANADA
Contact:

variable call address in ASM

Post 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.
User avatar
AJ
Member
Member
Posts: 2646
Joined: Sun Oct 22, 2006 7:01 am
Location: Devon, UK
Contact:

Post 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
User avatar
XCHG
Member
Member
Posts: 416
Joined: Sat Nov 25, 2006 3:55 am
Location: Wisconsin
Contact:

Post 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.
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.
kubeos
Member
Member
Posts: 138
Joined: Tue Jan 30, 2007 2:31 pm
Location: Kamloops BC, CANADA
Contact:

Post by kubeos »

Thanks XCHG,

That was exactly what I needed to know.
Post Reply