问题
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
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.
回答1:
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
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 (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.
来源:https://stackoverflow.com/questions/26570229/comparing-16-bit-numbers-in-nasm-produces-wrong-results