我是这个论坛的新手。 我对高级语言有一点经验(真的很少)。差不多一个月前,我认为在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]
但是很明显,人们想要增加寄存器的内容(因为它没有地址(或者它有吗?)??
答案 0 :(得分:3)
您的数字将迅速增长,而不仅仅是一位数。您应该做的是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
的注册表中时,将它加倍。