我正在尝试查找给定数字(用户输入)是偶数还是奇数。
我只是对一个no的二进制数字应用
AND
操作。使用1
,如果数字为奇数,那么操作将导致0
,输出数字将为奇数,否则我们将输出数字为偶数。
虽然逻辑似乎很简单,但它不适用于下面的代码。我没有得到代码中的问题。谁能告诉我问题出在哪里
section .data
userMsg db 'Please enter a number'
lenuserMsg equ $ - userMsg
even_msg db 'Even Number!'
len1 equ $ - even_msg
odd_msg db 'Odd Number!'
len2 equ $ - odd_msg
section .bss
num resb 5 ;Reserved 5 Bytes for Input
section .text
global _start ;must be declared for linker (gcc)
_start:
;User Prompt
mov ebx, 1 ;file descriptor (stdout)
mov ecx, userMsg ;message to write 'Please enter a number'
mov edx, lenuserMsg ;message length
mov eax, 4 ;system call number (sys_write)
int 0x80 ;call kernel
;Taking user input
mov ebx, 0 ;(stdin)
mov ecx, num
mov edx, 5 ;i/p length
mov eax, 3 ;system call number (sys_read)
int 0x80 ;call kernel
mov ax, [num]
and ax, 1
jz evnn ;Jump on Even
;Printing No. is Odd
mov ebx, 1 ;file descriptor (stdout)
mov ecx, odd_msg ;message to write 'Odd Number!'
mov edx, len2 ;message length
mov eax, 4 ;system call number (sys_write)
int 0x80 ;call kernel
jmp outprog ;Jump to exit
;Printing No. is Even
evnn:
mov ebx, 1 ;file descriptor (stdout)
mov ecx, even_msg ;message to write 'Even Number!'
mov edx, len1 ;message length
mov eax, 4 ;system call number (sys_write)
int 0x80 ;call kernel
;Exit
outprog:
mov eax, 1 ;system call number (sys_exit)
int 0x80 ;call kernel
答案 0 :(得分:2)
只关注手头的真正问题,好吗?如果将一个ASCII字符放在AL寄存器中,只需将其转换为数字,其余部分应该是自然的。在计算(二进制数和系统)中,整数奇数或偶数由位0确定。如果它是1,则它是奇数。如果为0,则为偶数。 (到目前为止,没有人特别强调这一点,我感到很惊讶。)
... ;OS puts a char in AL.
sub al,30h ;turn an ASCII char to one integer digit
shr al,1 ;Lets see how the flags responds below
jc .odd ;CF is set if the first bit (right-most, bit 0) is 1.
;do Even things
;skip pass .odd
.odd:
;do Odd things
答案 1 :(得分:1)
您的代码不起作用,因为当您询问用户输入数字时,您会读取ASCII编码的字符串。您需要首先调用atoi
(ASCII到INT)将字符串转换为计算机看到的“真实”数字。 glibc中包含atoi
。
extern atoi
push eax ; pointer to your string to be converted, eg '123'
call atoi
; now eax contains your number, 123
您还可以对最低有效位(位0)进行一点测试,以确定它是偶数还是奇数:
mov al, 01000_1101b
bt al, 0 ; copies the bit to the Carry Flag
jc its_odd ; jump if CF==1
; else - it's even (CF==0)
BT做什么,它将位复制到CF,你可以根据它进行条件跳转。
答案 2 :(得分:1)
mov ax, [num]
加载用户输入字符串的前2位数字,然后测试第一个数字。 所以你实际上是在测试第一个字符的ASCII码是否为。
2是因子10,因此您只需测试最后一位十进制数的低位,以确定基数为10的数字是偶数还是奇数。
由于'0'
的ASCII码是0x30,,您只需测试字符串最后一个ASCII字符的低位。
除非您需要测试atoi()
或其他一些不是因子10的模数,否则您无需致电n % 3
。(您可以测试{{1}通过仅查看最后一位数来查看},n % 2
和n % 5
。请注意,您不能只测试低十进制数的低2位来检查4的倍数,因为10不是4的倍数。 n % 10
,但100%4 = 0
。
因此,给定指针+长度,您可以使用30%4 = 2
/ TEST byte [last_char], 1
。例如在sys_read之后,你有一个指向ECX中字符串的指针,以及EAX中的返回值(字节数)。
jnz odd
然后是奇数/偶数的实际测试:在最后一个ASCII数字上只有一个测试和分支:
;Taking user input
mov ebx, 0 ;(stdin)
mov ecx, num
mov edx, 5 ;i/p length
mov eax, 3 ;system call number (sys_read)
int 0x80 ;call kernel
; Now we make the unsafe assumption that input ended with a newline
; so the last decimal digit is at num+eax-1.
; now do anything that is common to both the odd and even branches,
; instead of duplicating that in each branch.
答案 3 :(得分:-1)
`section .bss
num resb 1
section .data
msg1 db'enter a number',0xa
len1 equ $-msg1
msg2 db' is even',0xa
len2 equ $-msg2
msg3 db'is odd',0xa
len3 equ $-msg3
section .text
global _start
_start:
mov edx,len1
mov ecx,msg1
mov ebx,1
mov eax,4
int 80h
mov ecx,num
mov ebx,0
mov eax,3
int 80h
mov al,[num]
add al,30h
and al,1
jz iseven
jmp isodd
isodd:
mov edx,len3
mov ecx,msg3
mov ebx,1
mov eax,4
int 80h
jmp exit
iseven:
mov edx,len2
mov ecx,msg2
mov ebx,1
mov eax,4
int 80h
jmp exit
exit:
mov eax,1
int 80h`