【问题标题】:Unsigned division in nasmnasm 中的无符号除法
【发布时间】:2014-10-20 02:14:47
【问题描述】:

我一直在尝试调试一个小汇编程序,在该程序中我要求除数和除数,并且必须输出商和余数。但是由于某种原因,我的商和余数没有输出到屏幕上。这是我的代码:

segment .data

prompt db "Please enter a number: ", 10
promptLen equ $-prompt
prompt2 db "Please enter the divisor: ", 10
prompt2Len equ $-prompt2
prompt3 db "Your quotient is: ", 10
prompt3Len equ $-prompt3
prompt4 db "Your remainder is: ", 10
prompt4Len equ $-prompt4

segment .bss

inputNum resb 2
inputDiv resb 2
quotient resb 2
remainder resb 2

segment .text

global _start

_start:

mov eax, 4
mov ebx, 1
mov ecx, prompt
mov edx, promptLen
int 80h

mov eax, 3
mov ebx, 0
mov ecx, inputNum
mov edx, 2
int 80h

mov eax, 4
mov ebx, 1
mov ecx, prompt2
mov edx, prompt2Len
int 80h

mov eax, 3
mov ebx, 0
mov ecx, inputDiv
mov edx, 2
int 80h

xor edx, edx
mov ax, [inputNum]
mov bx, [inputDiv]
sub ax, '0'
sub bx, '0'

div bx

add ax, '0'
add dx, '0'
mov [quotient], ax
mov [remainder], dx

mov eax, 4
mov ebx, 1
mov ecx, prompt3
mov edx, prompt3Len
int 80h

mov eax, 4
mov ebx, 1
mov ecx, [quotient]
mov edx, 2
int 80h

mov eax, 4
mov ebx, 1
mov ecx, prompt4
mov edx, prompt4Len
int 80h

mov eax, 4
mov ebx, 1
mov ecx, [remainder]
mov edx, 2
int 80h
jmp exit

exit:

mov eax, 1
xor ebx, ebx
int 80h

如果有人能帮助我理解我做错了什么,我将不胜感激。

【问题讨论】:

  • 你输入的是什么数据?
  • @paxdiablo,我测试了它,我的除数是 5,除数是 2
  • @paxdiablo,成功了!谢谢你!然而,使用相同的数据,我得到 1 作为商,3 作为余数。知道为什么吗?

标签: assembly nasm integer-division


【解决方案1】:

系统调用 4(写入)需要一个 char * 作为其在 ecx 中的缓冲区地址。使用您的代码:

mov eax, 4          ; sys_write
mov ebx, 1          ; standard output
mov ecx, [quotient] ; here, ecx <- your character code
mov edx, 2          ; two bytes (hmmm)
int 80h

您正在加载ecx 与输入的实际数据,而不是它的地址。

你需要做的是用字符的地址加载ecx,这可能只是这样的:

mov ecx, quotient ; here, ecx <- your character address

您可能还希望将字节数减少到一而不是二。将整数转换为字符的方式(添加 '0')无论如何都只适用于单字符数字,因此您只需要最低有效字节(x86 的最低内存地址中的字节)。

其余部分同上。


顺便说一句,当你修复它时,你仍然会得到一个有趣的结果。 5 除以 2 商为 1,余数为 3,显然是错误的。

这与您输入数据并将值加载到axbx 的方式有关。

由于您要为每个数字读取 两个 字节,内存中会加载数字本身 '5'0x35,后跟换行符 0x0a

然后,当您将两个字节的单词加载到ax中时,它会以0x0a35结尾。

从每一个中减去0x0030 ('0') 后,您最终得到0x0a050x0a02,即十进制的25652562。当您将 这些 数字相除时,您确实会得到 1 的商和 3 的余数。

要解决这个问题,您可以简单地丢弃 0x0a00,但在加载值时,通过更改:

xor edx, edx
mov ax, [inputNum]
mov bx, [inputDiv]
sub ax, '0'
sub bx, '0'

进入:

xor edx, edx
mov ax, [inputNum]
mov bx, [inputDiv]
and ax, 0xff          ; add these
and bx, 0xff          ;   two lines.
sub ax, '0'
sub bx, '0'

【讨论】:

  • 成功了!谢谢你!然而,使用相同的数据,我得到 1 作为商,3 作为余数。知道为什么吗?
  • 关于如何进行十进制转换的任何建议,以便我不会仅限于一个字符数字?
  • @user116317,我已经更新了你为什么会得到奇怪结果的答案。至于如何处理多个数字,这可能是关于 SO 的另一个问题。这样你会得到更多的回应,而不是在评论框中提问。
猜你喜欢
  • 1970-01-01
  • 2016-01-24
  • 1970-01-01
  • 1970-01-01
  • 2020-12-23
  • 2016-05-10
  • 1970-01-01
  • 1970-01-01
  • 2015-12-05
相关资源
最近更新 更多