用x86 32位Linux打印一个整数sys_write(NASM)

我是这个论坛的新手。 我对高级语言有一点经验(很less)。 大概在一个月前,我认为在linux上selectnasm(IA-32)之后,我开始从教程中学习,看看程序集是如何工作的。

现在,在结束之后,我试着写一个简单的程序,让你的计算机打印出100个数字(1 2 4 8 16 …)的列表,但是我甚至无法把它弄清楚。 我得到这个输出:

1PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP(continues)... 

程序是这样的:

 section .text global main main: mov word [num], '1' mov ecx, 100 doubl: push ecx ; to push the loop counter mov eax, 4 mov ebx, 1 mov ecx, num mov edx, 1 int 0x80 sub ecx, 30h add ecx, ecx ; shl ecx, 1 add ecx, 30h mov [num], ecx ; deleting this line I get 11111111111111111... pop ecx ; to pop the loop counter loop doubl exit: mov eax, 1 int 0x80 section .bss num resw 2 

看起来错误是在数字翻倍的部分,或者是存储在variables'num'中的那个部分,但是我不明白为什么会发生,以及如何解决。

顺便问一下,有人可以解释我什么时候使用方括号吗? 有规则什么的? 本教程将其称为“有效地址”,当我想要移动(或做某事)variables的内容而不是variables的地址时,它看起来像我必须使用括号。 但是我很困惑。 我看到它用在:

 mov ebx, count inc word [ebx] mov esi, value dec byte [esi] 

但不是很明显,要增加registry的内容(因为它没有一个地址(或是否?)?

您的号码将快速增长,不只是一个数字。 你应该做的是有一个整数在num而不是一个字符,然后将该整数转换为可以用sys_write打印的字符串。

这里有一种做转换的方法:重复除以10,最后得到最低的数字作为余数:

 ; Input: ; EAX = integer value to convert ; ESI = pointer to buffer to store the string in (must have room for at least 10 bytes) ; Output: ; EAX = pointer to the first character of the generated string int_to_string: add esi,9 mov byte [esi],0 ; String terminator mov ebx,10 .next_digit: xor edx,edx ; Clear edx prior to dividing edx:eax by ebx div ebx ; eax /= 10 add dl,'0' ; Convert the remainder to ASCII dec esi ; store characters in reverse order mov [esi],dl test eax,eax jnz .next_digit ; Repeat until eax==0 ; return a pointer to the first digit (not necessarily the start of the provided buffer) mov eax,esi ret 

你可以这样使用:

  mov dword [num],1 ... mov eax,[num] ; function args using our own private calling convention mov esi,buffer call int_to_string ; eax now holds the address that you pass to sys_write ... section .bss num resd 1 buffer resb 10 

你的倍数可以简化为shl dword [num],1 。 或者更好的是,在add eax,eax时候,它还在一个寄存器中。