NASM 带有 cx 寄存器的汇编程序无限循环
NASM assembler infinite loop with cx register
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 times.But 它进入了无限循环,我不明白为什么?
我认为 cx 寄存器不会减少或其他什么?
您正在尝试将 cx
寄存器用于循环计数,同时需要使用 ecx
作为输出参数。由于 cx
是 ecx
的低 16 位,因此您破坏了循环计数。
您需要使用一些其他寄存器(在系统调用期间未使用)来进行循环计数,或者将计数存储在堆栈上的局部变量中。
你有很多问题。
Linux 程序的默认入口点是 _start
。您的程序首先在标签 _start
而不是 initial
处执行,因此您的循环计数器未被初始化。
部分名称没有 :
,global
1[=25 的标签也没有=]
您缺少 SYS_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
行可以删除。
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 times.But 它进入了无限循环,我不明白为什么? 我认为 cx 寄存器不会减少或其他什么?
您正在尝试将 cx
寄存器用于循环计数,同时需要使用 ecx
作为输出参数。由于 cx
是 ecx
的低 16 位,因此您破坏了循环计数。
您需要使用一些其他寄存器(在系统调用期间未使用)来进行循环计数,或者将计数存储在堆栈上的局部变量中。
你有很多问题。
Linux 程序的默认入口点是
_start
。您的程序首先在标签_start
而不是initial
处执行,因此您的循环计数器未被初始化。部分名称没有
:
,global
1[=25 的标签也没有=]您缺少
SYS_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
行可以删除。