Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux 部件中的查找编号为偶数/奇数_Linux_Assembly_X86_Nasm - Fatal编程技术网

Linux 部件中的查找编号为偶数/奇数

Linux 部件中的查找编号为偶数/奇数,linux,assembly,x86,nasm,Linux,Assembly,X86,Nasm,我试图找出一个给定的数字(由用户输入)是偶数还是奇数 我只是对编号的二进制数字应用和运算。对于1,如果数字是奇数,则运算结果将是0,我们将输出奇数,否则我们将输出偶数 虽然逻辑看起来很简单,但在下面的代码中它不起作用。我不明白代码中的问题在哪里。谁能告诉我哪里出了问题 section .data userMsg db 'Please enter a number' lenuserMsg equ $ - userMsg even_msg db 'Even Number!

我试图找出一个给定的数字(由用户输入)是偶数还是奇数

我只是对编号的二进制数字应用
运算。对于
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

您的代码不起作用,因为当您要求用户输入数字时,您读取的是ASCII编码的字符串。您需要先调用
atoi
(ASCII到INT)将字符串转换为计算机看到的“实数”<代码>atoi包含在glibc中

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,您可以在此基础上进行条件跳转。

mov ax,[num]加载用户输入字符串的前两位,您正在测试第一位所以您实际上是在测试第一个字符的ASCII码是否为偶数

2是10的系数,因此只需测试最后一个十进制数字的低位,即可确定以10为基数的数字是偶数还是奇数

由于
'0'
的ASCII码是0x30,您可以只测试字符串最后一个ASCII字符的低位

您不需要调用
atoi()
,除非您需要测试
n%3
或其他不是10的系数的模数。(即,只需查看最后一位数字即可测试
n%2
n%5
、和
n%10
)。请注意,您不能只测试低位十进制数字的低位2位来检查4的倍数,因为10不是4的倍数。e、 g.
100%4=0
,但
30%4=2


因此,给定一个指针+长度,您可以使用
测试字节[last_char],1
/
jnzodd
。e、 g.输入后,在ECX中有一个指向字符串的指针,在EAX中有一个返回值(字节计数)

然后是奇数/偶数的实际测试:最后一个ASCII数字上只有一个测试和分支:

; We still have num in ECX, because int 0x80 doesn't clobber any regs (except for eax with the return value).
    test byte [ecx + eax - 1], 1
    jnz  odd

把注意力集中在手头的真正问题上,好吗?如果说一个ASCII字符放在AL寄存器中,只需将它转换成一个数字,其余的就应该是自然的。在计算(二进制数和系统)中,整数的奇数或均匀度由位0决定。如果是1,则为奇数。如果为0,则为偶数。(我感到惊讶的是,到目前为止,还没有人特别强调这一点)


只是一个想法——(我已经30多年没有编写asm了),但是你确定输入num被视为一个数字吗?e、 g.我输入字母“a”时得到奇数,即ascii 65。是的,测试数字的低位是正确的,因为它们存储在base2中。如果奇偶分支只设置指针和长度,而不复制
int0x80
系统调用的其余部分,那么程序可能会更紧凑。您应该至少用系统调用号码的符号名(例如,
sys\u write
)来注释代码。您可以使用这样一个事实,即从输入读取的字符数在sys\u read的
eax
中返回。一种方法是使用返回的字符数作为索引来查找最右边的ASCII数字。返回的字符数包括终止字符(0x0a)。这可以通过将
mov-ax、[num]
和ax,1
替换为
mov-al、[num+eax-2]
和al,1
来实现。这假设缓冲区足够大,可以容纳包括终止字符在内的最长数字。如果您打算对从控制台输入的数字(除偶数/奇数外)执行任何其他操作,您可能需要将返回的字符串转换为整数,并处理该整数。最好对代码进行注释。它将帮助任何不熟悉特定系统呼叫号码的人提供帮助,而无需研究您所在的平台。它还将使您自己的调试更加容易。
test al,1
/
jnz
的工作原理相同,但代码大小稍小,效率稍高(test/jnz可以宏融合到单个测试中并分支uop,不像BT)<代码>bt r,r/i是有效的,但是:只有一个uop(与第一个参数的内存操作数不同,在这种情况下,它比在内存参数上测试慢得多,因为位索引影响内存地址)。更重要的是,由于2是10的一个因子,所以只需要测试最后一个十进制数字的低位。由于
'0'
的ASCII码是0x30,您可以只测试字符串最后一个ASCII字符的低位。您不需要调用atoi,除非您需要测试
n%3
或其他不是10的系数的模数。(也就是说,你可以只看最后一个数字来测试
n%2
n%5
n%10
)。正如我在回答中指出的那样,
sub al,30h
不会影响低位,所以你不需要在测试低位之前进行测试。(另外,
test al,1
比SHR更有效,并且不会破坏值。)基本上,我回答的全部要点是解释,测试数字的低位会告诉你它是奇数还是偶数。(虽然我在回答问题时花了更多的时间解释为什么只测试ASCII字符串的低位就足够了,而你不能只看低位十进制数字的低位2来判断一个数字是否是4的倍数。)@PeterCordes我喜欢你为帮助人们所做的事,但有时我们需要从OP的代码和描述中去掉这一个问题。试着从字里行间读,因为有时候OP不知道如何表达他的/问题
; We still have num in ECX, because int 0x80 doesn't clobber any regs (except for eax with the return value).
    test byte [ecx + eax - 1], 1
    jnz  odd
    ...                  ;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
`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`