汇编子例程被调用两次,甚至没有从主程序调用
我正在尝试定义一些在其中调用 printf 的子例程。 一个非常简单的示例如下:
extern printf
LINUX equ 80H
EXIT equ 60
section .data
intfmt: db "%ld", 10, 0
segment .text
global main
main:
call os_return ; return to operating system
os_return:
mov rax, EXIT ; Linux system call 60 i.e. exit ()
mov rdi, 0 ; Error code 0 i.e. no errors
int LINUX ; Interrupt Linux kernel
test:
push rdi
push rsi
mov rsi, 10
mov rdi, intfmt
xor rax, rax
call printf
pop rdi
pop rsi
ret
这里 test 只是调用 printf 将数字 10 输出到屏幕。我不希望它被调用,因为我没有调用它。
然而,在编译和运行时:
nasm -f elf64 test.asm
gcc -m64 -o test test.o
我得到输出:
10
10
我完全感到困惑,想知道是否有人可以解释为什么会发生这种情况?
I'm trying to define some subroutines that have calls to printf in them.
A very trivial example is as follows:
extern printf
LINUX equ 80H
EXIT equ 60
section .data
intfmt: db "%ld", 10, 0
segment .text
global main
main:
call os_return ; return to operating system
os_return:
mov rax, EXIT ; Linux system call 60 i.e. exit ()
mov rdi, 0 ; Error code 0 i.e. no errors
int LINUX ; Interrupt Linux kernel
test:
push rdi
push rsi
mov rsi, 10
mov rdi, intfmt
xor rax, rax
call printf
pop rdi
pop rsi
ret
Here test just has a call to printf that outputs the number 10 to the screen. I would not expect this to get called as I have no call to it.
However when compiling and running:
nasm -f elf64 test.asm
gcc -m64 -o test test.o
I get the output:
10
10
I'm totally baffled and wondered if someone could explain why this is happening?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
int 80H
调用 32 位系统调用接口,该接口 a) 使用 32 位系统调用号,b) 供 32 位代码使用,而不是 64 位代码。您的代码实际上是使用随机参数执行umask
系统调用。对于 64 位系统调用,请改用 syscall 指令:
int 80H
invokes the 32-bit system call interface, which a) uses the 32-bit system call numbers and b) is intended for use by 32-bit code, not 64-bit code. Your code is actually performing aumask
system call with random parameters.For a 64-bit system call, use the
syscall
instruction instead:我想说的是,您对
exit
的调用失败了,因此当它返回时,它会转到test
函数,该函数会打印前 10 个。然后当您使用 < code>ret 您将返回到
调用 os_return
之后的指令,即os_return
。对 exit 的调用再次失败,并再次转到test
函数。但这次ret
从main
函数返回,程序结束。关于为什么
exit
调用失败,我无法判断,因为我没有可用的 64 位系统。但是您可以从 libc 中反汇编 exit 函数,看看它是如何完成的。我的猜测是int LINUX
接口只是 32 位的,因为它的存在只是为了历史兼容性,而 64 位 Linux 并不那么古老。I would say that your call to
exit
is failing, so when it returns, it falls through to thetest
function, that prints the first 10.Then when you return with
ret
you go back to the instruction just after thecall os_return
, that is, wellos_return
. The call to exit fails again and falls through to thetest
function again. But this time theret
returns from themain
function and the program ends.About why is the
exit
call failing, I cannot tell as I don't have a 64-bit system available. But you could disassemble theexit
function from libc and see how it is done there. My guess is that theint LINUX
interface is 32-bit only, as it exists only for historic compatibility, and 64-bit linux in not so old.