section .data:
msg1: db "Hello 10 times!"
msglen1: equ $-msg1
section .text:
global _initial:
global _start:
global _end:
_initial:
mov cx,10
_start:
dec cx
mov ecx,msg1
mov edx,msglen1
mov eax,4
int 80h
cmp cx,0
jz _end
jmp _start
_end
mov eax,1
int 80h
上面的代码必须生成“Hello 10 times”10 次。但它进入了无限循环,我不明白为什么? 我认为 cx 寄存器不会减少或其他什么?
最佳答案
你有很多问题。
Linux 程序的默认入口点是
_start
。您的程序从标签_start
而不是initial
开始执行,因此您的循环计数器未被初始化。部分名称中没有
的标签也没有:
,global
1SYS_Write
系统调用缺少一个参数。 32 位系统调用是 documented in a table :您需要将EBX 设置为文件描述符。标准输入=0,标准输出=1,标准错误=2。您想写入控制台,因此您需要在调用
Int 80h
之前将 EBX 设置为 1
您正在破坏
SYS_Write
系统调用的参数之一 (ECX)。 CX 和 ECX 是同一寄存器的一部分。 CX 是 ECX 的低 16 位。更改 CX 会更改 ECX。您需要为循环计数器使用其他一些寄存器。 ESI、EDI 和 EBP 当前未在您的代码中使用。将所有出现的 CX 更改为 32 位寄存器 ESI。
您的代码可能如下所示:
section .data
msg1: db "Hello 10 times!", 10
; Add 10 on the end of the string for Line Feed
; so each message prints on separate line
msglen1 equ $-msg1
section .text
global _initial
global _start
global _end
_start:
mov esi, 10 ; Initialize loop counter
_msgloop:
dec esi ; Decrement loop counter
mov ebx, 1 ; File Descriptor 1 = Write to Standard Output (STDOUT)
mov ecx, msg1 ; Address of message to print
mov edx, msglen1 ; Length of message to print
mov eax, 4 ; SYS_Write system call = 4
int 80h
cmp esi, 0 ; Has the loop counter reached 0?
jz _end ; If it has then we are done
jmp _msgloop ; otherwise go back and print message again
_end:
mov eax,1 ; SYS_Exit system call
int 80h
你可以这样重写你的循环:
section .data
msg1: db "Hello 10 times!", 10
; Add 10 on the end of the string for Line Feed
; so each message prints on separate line
msglen1 equ $-msg1
section .text
global _start
_start:
mov esi, 10 ; Initialize loop counter
.msgloop:
mov ebx, 1 ; File Descriptor 1 = Write to Standard Output (STDOUT)
mov ecx, msg1 ; Address of message to print
mov edx, msglen1 ; Length of message to print
mov eax, 4 ; SYS_Write system call = 4
int 80h
dec esi ; Decrement loop counter
jnz .msgloop ; If loop counter hasn't reached zero then print again
mov eax,1 ; SYS_Exit system call
int 80h
脚注:
- 1您不需要将
initial
和end
设为全局,因为您没有链接到任何其他目标文件。可以删除那些global
行。
关于linux - 带有 cx 寄存器的 NASM 汇编器无限循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57377418/