简体   繁体   中英

Why call and ret functions work like this in assembly?

So, I was messing around with assembly, and stumbled upon weird thing. Before writing anything, I set registers to these values:

AX 0000, BX 0000, SP 00FD.

Lets say, that we write simple code, which increases registers AX and BX:

A100
INC AX
CALL 0200

A200
INC BX
RETN

After writing it, I tried to see how registers change when executing commands, one by one, using T command. First time, it increases AX , moves to 0200 , increases BX and returns. Here is the weird bit: when it returns, it executes command: ADD [BX+SI],AX and then calls 0200 again.

When it calls 0200 again, it repeats itself, but now, when it returns, it returns to CALL 0100 command (not to CALL 0200 ) and increases AX again and so on. Why is this happening?

I have image of full output, maybe this can help understand my question better?: http://s18.postimg.org/wt6eracg9/Untitled.png

Based on your screenshots, your code seems to be this (filled with nop 's, disassembled with udcli ):

echo 40 e8 fc 00 01 00 e8 f7 00 e8 f4 ff x{1..244} 43 c3 | sed 's/x[0-9]*\>/90/g' | udcli -o 0x100 -x -16
0000000000000100 40               inc ax
0000000000000101 e8fc00           call word 0x200
0000000000000104 0100             add [bx+si], ax
0000000000000106 e8f700           call word 0x200
0000000000000109 e8f4ff           call word 0x100
000000000000010c *** never reached ***

0000000000000200 43               inc bx                  
0000000000000201 c3               ret

The code flow is the following, line by line:

0000000000000100 40               inc ax

ax gets incremented.

0000000000000101 e8fc00           call word 0x200

Return address 0x104 gets pushed to the stack, ip (instruction pointer) is set to 0x200.

0000000000000200 43               inc bx

bx gets incremented.

0000000000000201 c3               ret

Near return, that is, ip is popped from stack. New ip will be 0x104.

0000000000000104 0100             add [bx+si], ax

The value of ax is added to the word value at [bx+si] .

0000000000000106 e8f700           call word 0x200

Return address 0x109 gets pushed to the stack, ip (instruction pointer) is set to 0x200.

0000000000000200 43               inc bx

bx gets incremented.

0000000000000201 c3               ret

Near return, that is, ip is popped from stack. New ip will be 0x109.

0000000000000109 e8f4ff           call word 0x100

Return address 0x10c gets pushed to the stack, ip (instruction pointer) is set to 0x100. So this is actually an infinite recursive function and will run out of stack.

So your problem is that you don't define the code after CALL 0200 . There happens to be 01 00 ( add [bx+si], ax ) and after return it will be executed, and after it other undefined instructions.

My advice: download any decent assembler (NASM, YASM, FASM...) ASAP and don't ruin your life trying to write assembly code with DEBUG. Trying to write assembly programs with DEBUG is an attempt destined to fail.

可能的原因是您没有退出,没有使用DOS的0x4c服务,并且程序绑定了代码并开始执行随机命令,或者执行流程命中了一些ret指令,其中不使用任何call ,因此然后会表现异常。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM