>我有一个汇编程序,它可以在一行上打印出从 1 到 9 的数字,如下所示:123456789。我想要的是将这些值分别打印在一行上;每行一个数字。
我尝试实现新行,但在我的代码中抛出错误分段错误(核心转储(。我对组装仍然很新鲜,所以我真的不知道如何找出为什么这不起作用。它只打印第一个数字 (1(,然后抛出该错误。
我尝试换行的代码:
mov dl, 13
mov ah, 02h
int 21h
mov dl, 10
mov ah, 02h
int 21h
我的代码:
_start:
mov ecx, 10
mov eax, '1'
L1:
mov [num], eax
mov eax, 4
mov ebx, 1
push ecx
mov ecx, num
mov edx, 1
int 0x80
mov eax, [num]
sub eax, '0'
inc eax
add eax, '0'
pop ecx
loop L1
mov eax, 1
int 0x80
section .bss
num resb 1
您应该使用相同的系统调用来打印用于打印数字的换行符。
此外,Linux中的换行符只是LF(char 10(,而不是CR(char 13(,然后是像Windows/DOS使用的LF。
如何在 x86 汇编中的 Linux 上打印到 stdout
此答案描述了每个参数对 Linux 打印系统调用的作用,这就是您通过提高int 0x80
调用的内容。
系统调用使用寄存器传入其参数。在链接的答案中,eax
是系统调用号码(4 = 打印(,ebx
是目标流(1 = stdout(,ecx
是指向要打印的数据的指针,edx 是要打印的数据的长度。
因此,在循环中实际执行打印的代码是:
mov [num], eax ; Moves the character in eax to the buffer pointed to by num.
mov eax, 4 ; Moves 4 into eax, i.e. selects the print system call.
mov ebx, 1 ; Moves 1 into ebx, i.e. selects stdout as the destination.
mov ecx, num ; Moves the address where your text is stored into ecx.
mov edx, 1 ; Moves the number of bytes to characters (1) into edx.
int 0x80 ; Executes a Linux system call using the above parameters.
要打印换行符,您只需在此代码之前eax
包含换行符(十进制字符 10 位(,而不是数字字符。因此,例如,在此代码之前添加mov eax, 10
将打印换行符而不是数字。
如何使其与现有循环一起工作
"我的代码"部分中num
是存储要打印的数据的缓冲区。但是,此代码也使用此内存来跟踪它打印的最后一个数字。因此,有两种方法可以在循环之间丢失该信息:
选项 1:只需将缓冲区的大小从 1 字节增加到 2,然后将换行符放在第二个字节中。然后,您只需将2
移动到edx
而不是1
告诉 Linux 您要打印 2 个字符,从而在每次循环迭代中打印数字和换行符。
选项 2:分配另一个单字节缓冲区来存储换行符。将换行符移动到此处,然后在打印循环中的数字的系统调用之后进行第二次系统调用以打印换行符。例如,如果你的新缓冲区被称为"lfbuffer",那么你可以在现有循环的int 0x80
行之后添加以下代码:
mov byte [lfbuffer], 10 ; Moves the a line feed to the buffer pointed to by lfbuffer.
mov eax, 4 ; Moves 4 into eax, i.e. selects the print system call.
mov ebx, 1 ; Moves 1 into ebx, i.e. selects stdout as the destination.
mov ecx, lfbuffer ; Moves the address where your line feed is stored into ecx.
mov edx, 1 ; Moves the number of bytes to characters (1) into edx.
int 0x80 ; Executes a Linux system call using the above parameters.