我是这个论坛的新手。我对高级语言有一点经验(很少)。将近一个月前,我认为查看汇编的工作方式是一个好主意,因此在Linux上选择nasm(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
看起来错误在于将数字加倍的部分或将其存储在变量“ num”中的部分,但我不知道为什么会发生以及如何解决。
顺便说一句,有人可以向我解释何时确切使用方括号?有规则吗?本教程将其称为“有效地址”,当我想移动变量的内容(或对其进行某些处理)而不是将其移至变量的地址时,似乎必须使用方括号。但是我对此很困惑。我看到它用在:
mov ebx, count inc word [ebx] mov esi, value dec byte [esi]
但是人们是否想增加寄存器的内容不是很明显(因为它没有地址(或者没有地址吗?)?
您的数字将迅速增长,而不仅仅是一个数字。您应该做的是输入一个整数num而不是一个字符,然后将该整数转换为可以使用打印的字符串sys_write。
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 ; ecx = length 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。
shl dword [num],1
add eax,eax