装配中查找编号为偶数/奇数

时间:2016-01-17 02:54:18

标签: linux assembly x86 nasm

我正在尝试查找给定数字(用户输入)是偶数还是奇数。

  

我只是对一个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

4 个答案:

答案 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 % 2n % 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`