为何在NASM中执行int 0x80系统调用后需重新赋值寄存器参数?
为什么重复调用Linux系统调用时需要重新设置eax和ebx寄存器?
我正在学习NASM汇编,编写了如下Hello World程序:
section .text: global _start _start: mov edx, len mov ecx, msg mov ebx, 1 mov eax, 4 int 0x80 mov edx, len2 mov ecx, msg2 mov ebx, 1 mov eax, 4 int 0x80 mov eax, 1 int 0x80 section .data: msg db "Let's test this thing!" len equ $ - msg msg2 db "This is the second line." len2 equ $ - msg2
若省略第二次int 0x80调用前的mov eax, 4和mov ebx, 1,程序仅打印第一行,无法打印第二行;重新赋值这两个寄存器后则能正常打印两行。我未修改过这些寄存器的值,疑惑为何需要重新赋值才能再次执行系统调用?
解答
你得明白,通过int 0x80触发的老式Linux系统调用不会保证调用后寄存器的值保持不变——哪怕你自己没动过这些寄存器,内核处理完系统调用后完全可能修改它们的内容。
具体到你的情况:
eax寄存器的作用是传递系统调用号(比如4对应sys_write),但系统调用返回时,内核会把调用的返回值写入eax。sys_write成功时返回写入的字节数,所以第一次调用后eax里已经不是4了,而是第一行文本的长度数值。ebx在这里用来传递文件描述符(1代表标准输出),虽然有些场景下它可能没被修改,但内核并没有承诺会保留它的值。依赖系统调用后寄存器还维持原值,本身就是完全不可靠的行为。
所以每次发起系统调用前,都必须明确设置好所有需要的寄存器参数,不能假设之前的值还存在。这是汇编层面调用系统调用的基本规则——内核不会帮你保存这些寄存器的状态,调用后它们的值属于未定义范畴(除了专门用来返回结果的寄存器)。
内容的提问来源于stack exchange,提问作者Jake StBu
相关产品推荐
相关产品推荐

