比较nasm中的16位数字会产生错误的结果 [英] Comparing 16 bit numbers in nasm produces wrong results
问题描述
我刚刚开始学习汇编.我正在以32位模式编码nasm.我正在尝试比较用户输入的3个数字并打印最大的数字.但是,如果我只使用resb 2为每个数字保留16位,我似乎无法正确比较数字.但是,当我使用resw 2为数字保留32位时,我确实得到了正确的结果.我不明白为什么这是案子.这是我的代码:
I have just started learning assembly. I am coding nasm in 32 bit mode. I am trying to compare 3 numbers inputted by the user and print the largest number. However, I cannot seem to correctly compare the numbers if I only reserve 16 bits for each number using resb 2. I do, however, get correct results when I reserved 32 bits for the numbers using resw 2. I cannot understand why this is the case. Here is my code:
SYS_EXIT equ 1
SYS_WRITE equ 4
SYS_READ equ 3
STD_IN equ 0
STD_OUT equ 1
segment .data
msg1 db "Enter first number",0xA
msg1_len equ $- msg1
msg2 db "Enter second number",0xA
msg2_len equ $- msg2
msg3 db "Enter third number",0xA
msg3_len equ $- msg3
msg4 db "Largest number is ",0xA
msg4_len equ $- msg4
segment .bss
num1 resb 2
num2 resb 2
num3 resb 2
res resb 2
section .text
global _start
_start:
mov eax, SYS_WRITE
mov ebx, STD_OUT
mov ecx, msg1
mov edx, msg1_len
int 0x80
mov eax, SYS_READ
mov ebx, STD_IN
mov ecx, num1
mov edx, 2
int 0x80
mov eax, SYS_WRITE
mov ebx, STD_OUT
mov ecx, msg2
mov edx, msg2_len
int 0x80
mov eax, SYS_READ
mov ebx, STD_IN
mov ecx, num2
mov edx, 2
int 0x80
mov eax, SYS_WRITE
mov ebx, STD_OUT
mov ecx, msg3
mov edx, msg3_len
int 0x80
mov eax, SYS_READ
mov ebx, STD_IN
mov ecx, num3
mov edx, 2
int 0x80
mov ecx, [num1]
cmp ecx, [num2]
jg check_third
mov ecx, [num2]
check_third:
cmp ecx, [num3]
jg result
mov ecx, [num3]
result:
mov [res], ecx
mov eax, SYS_WRITE
mov ebx, STD_OUT
mov ecx, msg4
mov edx, msg4_len
int 0x80
mov eax, SYS_WRITE
mov ebx, STD_OUT
mov ecx, res
mov edx, 2
int 0x80
exit:
mov eax, SYS_EXIT
int 0x80
很抱歉,如果其中包含很多重复代码.我知道为什么当ASCII字符长度只有8位时,为什么需要2个字节来存储键盘输入(因为标准输入还将读取除数字之外的换行符).但是,我对nasm的工作方式一无所知,例如当我将16位内存移至32位寄存器时,nasm会如何反应,如何比较32位和16位值(它将进行带符号扩展还是仅填充)?二进制减法前为0).如果有人可以向我推荐有关nasm技术的资源,除了解释为什么我需要保留2个单词来进行比较,我将不胜感激.
Sorry if it has a lot of repeating code. I understand why I need 2 bytes to store keyboard input when supposedly ascii characters are only 8 bits in length (Since the standard input will also read the new line character aside from the digit). However, I do not know a lot of things about how nasm works such as how it reacts when I move 16 bits of memory to a 32 bit register, how it compares 32 bit and 16 bit values (will it do signed expansion or just pad 0 before binary subtraction). I would truly appreciate it if someone can recommend me resources on the technicalities of nasm aside from explaining why I need to reserve 2 words to do the comparison.
推荐答案
Nasm不会像其他汇编程序一样在标签上保留数据大小的记录.假设您输入1、2和3.那么存储在标签上的字节将是:
Nasm does not keep record of the size of the data at label like some other assemblers. Suppose you enter 1, 2 and 3. Bytes stored at your labels will then be:
num1: db 0x31, 0x0A
num2: db 0x32, 0x0A
num3: db 0x33, 0x0A
当您从标签num1
中移出32位数据时,实际上您也在从num2
中移出数据.因为小字节序的机器先存储最低有效字节,所以您会得到以下信息:
When you move 32 bits of data from label num1
, you are actually also moving data from num2
. Because little endian machines store least significant bytes first, you get something like:
mov ecx, 0x0A320A31 ; high bytes contain num2 and low bytes contain num1
cmp ecx, 0x0A330A32 ; high bytes contain num3 and low bytes contain num2
jg check_third
mov ecx, 0x0A330A32
check_third:
cmp ecx, 0x00000A33 ; high bytes contain res and low bytes contain num3
jg result
.....
resw 2
(或resd 1
)将起作用,因为保留内存被初始化为零.如Frank在评论中所述,您应该使用cl
而不是ecx
,因为在这种情况下,您只需要处理8位即可.
resw 2
(or resd 1
) would work because reserved memory is initialized to zeros. As Frank stated in the comment, you should use cl
instead of ecx
because 8 bits is all you need to handle in this case.
这篇关于比较nasm中的16位数字会产生错误的结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!