我有以下代码,我在这个website上在线运行:
section .bss
num resq 1
section .text
global _start
_start:
mov eax, 4
mov ebx, 1
mov ecx, msg
mov edx, len
int 0x80
mov eax, 3
mov ebx, 0
mov ecx, num
mov edx, 8
int 0x80
mov eax,[num]
cmp eax,0
jl negative_label
je equal_label
jg positive_label
equal_label:
mov eax,4
mov ebx,1
mov ecx,equal_text
mov edx,3
int 0x80
jmp exit
positive_label:
mov eax,4
mov ebx,1
mov ecx,pos_text
mov edx,3
int 0x80
jmp exit
negative_label:
mov eax,4
mov ebx,1
mov ecx,neg_text
mov edx,3
int 0x80
jmp exit
exit:
mov eax,1
mov ebx,0
int 0x80
section .data
msg db 'Hello, world!',0xa,0
len equ $ - msg
pos_text db "Poz"
neg_text db "Neg"
equal_text db "Nul"
字符串
我想检查用户输入的数字是正数、负数还是零。基本上,我想做一个程序,让用户输入数字,直到他们输入零(0),它打印出之前输入的所有数字的总和。
因此,如果用户的输入是:“1,-3,3,4”,预期输出将是“5”,因为这是上述数字的总和。
我尝试执行sub
指令将 num 值转换为number,但要么我做错了,要么这不是正确的方法。
请随意批评我的代码,我是一个初学者和解决方案将是伟大的。
3条答案
按热度按时间6rqinv9w1#
如果用户输入text“1,-3,3,4”,则 num 处的存储器将保存以下8个字节:0x31、0x2C、0x2D、0x33、0x2C、0x33、0x2C、0x34。
您的指令
mov eax,[num]
将检索前4个字节,以便EAX寄存器包含0x 332 D2 C31。EAX中的这个值并不反映您感兴趣的任何单个个位数,因此在对(个位数)数字进行分类的上下文中,将 this EAX与零进行比较没有意义。需要做的是在字符串上循环,同时验证,分类,转换,求和...
这是我的建议
字符串
只有当ECX中的最终总和恰好是一位数时,才可以使用下一个简化打印输出:
型
上面的代码片段表明,编写此任务并不是特别困难。我真的不能同意其他的答案之一,使用的话:
如果你是一个初学者,你应该从一个简单的程序开始
。组装起来不容易
。也很难
。也很难
dnph8jn42#
子方法仅适用于0 ≤ num ≤ 9。
mov eax, [num]
将4个字节(4个字符)移动到eax,因为eax是一个DWORD(4字节)寄存器(我在前面的回答中忘记了)。这导致eax将包含
0x332D2C31
(因为'1' = 0x 31;',' = 0x2C;'-' = 0x2D;'3' = ASCII中的0x 33,并且小端字节顺序反转字节顺序)。使用al
寄存器代替eax(因为它是一个1字节寄存器)。所以你的代码应该看起来像这样:字符串
并且(这是可选的,它不会影响代码,但是)您应该使用
resb 8
而不是resq 1
。它做同样的事情,但看起来更好,如果你保留8个1字节的值(8个字符),而不是保留1个8字节的值(= C中的uint64_t
)。More about little endian and byte orders的数据。
mec1mxoz3#
跳转到
jg
是因为:输入的数字存储为ASCII字符,而不是数字,例如,如果我尝试比较ASCII '0'字符(在ASCII表中为48,在内存中存储为48),它将始终大于数字0(在内存中存储为0)。
如果你只处理1位数和无符号数,你可以通过从eax(
sub eax, 48
)中减去48来转换它。你的代码将无法从这里开始工作(这只是汇编中一个功能齐全的求和程序的一个步骤),因为还有更多的困难:
,
个字符分割输入文本write
系统调用只能打印ASCII字符。以下文档和网站可以帮助您入门: