Best way to simulate a call with jmp(dos assembly)
Asked Answered
T

2

1

I'm using a flat assembler on windows and have already simulated a call instruction with jmp but was wondering if there's a better way to do it with less code?(not using a call)

here's the code.

org 100h

mov al, 'x'

push come_back ; - simulated "call" -
jmp test_label  ; -   continued  -
come_back:     ; - end of simulated "call" -


mov al, 'y'

push come_back2 ; - simulated "call" -
jmp test_label  ; -   continued  -
come_back2:     ; - end of simulated "call" -

Looop:
jmp Looop


test_label:
mov ah, 0x0e
int 0x10
pop cx   ; - simulated "ret" -
jmp cx   ; - end of simulated "ret" 

This code just display's "xy", two char's to the console.

I don't want to use a call because i wan't a better understanding, and sometimes that involves doing things the wrong way. I'm new to assembly and didn't know what would be the best way to go about this.

Twitty answered 25/1, 2015 at 4:44 Comment(0)
D
1

This might work:

push $+5
jmp fn
; no label needed here

Some assemblers will interpret $ as the instruction address.

This is an infinite loop:

jmp $
Drivel answered 25/1, 2015 at 4:53 Comment(1)
I realize now you may need to add some more bytes to the push to account for the size of the push. Have a play!Drivel
B
2

You are doing it the same way the processor internally does it. You should be using call and ret to do it though. Each instruction takes time to execute. This is called a cycle. The more instructions you have, the more cycles it takes, thus taking more time to execute.

Internally, when the processor comes to a call instruction in your code, this happens:

  1. The processor pushes the address of the IP register after your call statement onto the stack.
  2. The processor changes the address of the IP register to the address of your call opcode.
  3. Execution resumes.

When the processor comes to a ret instruction in your code, this happens:

  1. The processor pops the 16-bit address off the stack and places it into the IP register.
  2. Execution resumes

Although it seems like a lot of steps, these steps happen without eating up cycles because it is built into the hardware of the CPU.

Brewton answered 25/1, 2015 at 4:55 Comment(2)
Good explanation, i'm glad you clarified this because i was unaware of how doing it my way was not optimized.Twitty
Another factor is the return address cache, which can go out of sync and cause calls to become much slower.Drivel
D
1

This might work:

push $+5
jmp fn
; no label needed here

Some assemblers will interpret $ as the instruction address.

This is an infinite loop:

jmp $
Drivel answered 25/1, 2015 at 4:53 Comment(1)
I realize now you may need to add some more bytes to the push to account for the size of the push. Have a play!Drivel

© 2022 - 2024 — McMap. All rights reserved.