【问题标题】:Arithmetic operations in assembly [duplicate]汇编中的算术运算[重复]
【发布时间】:2018-01-17 03:26:58
【问题描述】:
        SYS_EXIT  equ 1
    SYS_READ  equ 3
    SYS_WRITE equ 4
    STDIN     equ 0
    STDOUT    equ 1

segment .data 

    msg db "Please enter a digit ", 0xA,0xD 
    len equ $- msg 

segment .bss

    number1 resb 2 
    number2 resb 2 
    result resb 1 
    result2 resb 1


segment .text 

    msg2 db "Please enter a second digit", 0xA,0xD 
    len2 equ $- msg2 

    msg3 db "The sum is: "
    len3 equ $- msg3

    msg4 db "The minus is: "
    len4 equ $- msg4

global _start 

 _start: 

    mov eax, SYS_WRITE   ; System write      
    mov ebx, STDOUT      ; System output   
    mov ecx, msg         ; What to write
    mov edx, len     ; Length to write
    int 0x80             ; Interupt Kernel      

    mov eax, SYS_READ    ; System read
    mov ebx, STDIN       ;
    mov ecx, number1 
    mov edx, 2
    int 0x80            

    mov eax, SYS_WRITE        
    mov ebx, STDOUT         
    mov ecx, msg2          
    mov edx, len2         
    int 0x80

    mov eax, SYS_READ  
    mov ebx, STDIN  
    mov ecx, number2 
    mov edx, 2
    int 0x80        


    call add



add:
    mov eax, SYS_WRITE         
    mov ebx, STDOUT         
    mov ecx, msg3          
    mov edx, len3         
    int 0x80

    ;load number1 into eax and subtract '0' to convert from ASCII to decimal
    mov eax, [number1]
    sub eax, '0'
    ; do the same for number2
    mov ebx, [number2]
    sub ebx, '0'

    ; add eax and ebx, storing the result in eax
    add eax, ebx
    ; add '0' to eax to convert the digit from decimal to ASCII
    add eax, '0'

    ; store the result in result
    mov [result], eax

    ; print the result digit
    mov eax, SYS_WRITE        
    mov ebx, STDOUT
    mov ecx, result         
    mov edx, 1        
    int 0x80 

    ret

minus:

    mov eax, SYS_WRITE         
    mov ebx, STDOUT         
    mov ecx, msg4          
    mov edx, len4         
    int 0x80

    ;load number1 into eax and subtract '0' to convert from ASCII to decimal
    mov eax, [number1]
    sub eax, '0'
    ; do the same for number2
    mov ebx, [number2]
    sub ebx, '0'

    ; add eax and ebx, storing the result in eax
    sub eax, ebx
    ; add '0' to eax to convert the digit from decimal to ASCII
    add eax, '0'

    ; store the result in result
    mov [result2], eax

    ; print the result digit
    mov eax, SYS_WRITE        
    mov ebx, STDOUT
    mov ecx, result         
    mov edx, 1        
    int 0x80

    ret

mul:

   ;load number1 into eax and subtract '0' to convert from ASCII to decimal
    mov al, [number1]
    sub al, '0'
    ; do the same for number2
    mov bl, [number2]
    sub bl, '0'

    ; add eax and ebx, storing the result in eax
    mul bl
    ; add '0' to eax to convert the digit from decimal to ASCII
    add al, '0'

    ; store the result in result
    mov [result], al

    ; print the result digit
    mov eax, SYS_WRITE        
    mov ebx, STDOUT
    mov ecx, result         
    mov edx, 1        
    int 0x80

    ret


exit:    
    mov eax, SYS_EXIT   
    xor ebx, ebx 
    int 0x80

上面的代码是我到目前为止所做的,我试图添加数字,但 add 函数似乎被调用了两次,如下图所示。我想做的是加、减、乘和除这两个数字。我该怎么做,当我尝试添加 2 个数字时,有时它给了我这个输出分段错误。

【问题讨论】:

  • mov [result], eax 中,您将result 变量作为DWORD 而非result resb 1 中定义的BYTE 访问。这可能不是根本原因,但仍然是溢出。
  • 如何解决这个问题?我刚开始学习汇编。
  • 如何 - 继续学习,任何体面的课程/教程都应该教给你一定数量的基础知识,每次有人问到 SO 时帮助所有这些基础知识是非常浪费的,所以确保你用尽了共同点明显的知识来源,并且您有一些特别令人费解的部分,在向 SO 询问并指出您所做的研究以及令您困惑的事情之前,那些 Q 在这里做得更好。有关一些资源,请参阅 stackoverflow.com/tags/x86/info。在这种特殊情况下,只存储eax (mov [result],al) 的一个字节,或者通过result: resd 1resb 4 分配4B。
  • 看起来您正在使用 NASM 汇编程序,但我仍然建议您阅读这个超短的MASM guide,因为它只包含少量 NASM 不兼容的语法,以及那里的大部分信息是通用的或与 NASM 兼容的,它还可以处理数据大小等等,因此它应该可以很好地概述您必须搜索的详细信息。为自己找到一些有效的调试器解决方案是另一个绝对必要的步骤。如果你会掌握gdb,对你有好处,我放弃并从github编译edb
  • 为什么您的问题需要输出图像?只需将文本复制到您的问题中即可。

标签: assembly x86


【解决方案1】:

您在 _start 块的中间定义了您的函数。

在调试器中单步执行您的代码,并注意在call add 返回后,继续执行从add 标签开始的指令。

最终当您到达ret 时崩溃,即当您尝试从_start 访问ret 时(因为堆栈的顶部是argc,而不是地址,在System V ABI 中的进程启动时)。或者你甚至可能更早地犯错;你没有发布调试器输出,我也没有在脑海中模拟它来看看会发生什么。

这就是The sum is: ? 被打印两次的原因。

我猜你的代码也无法处理多位数字,所以你得到了 ASCII 码 '0' + 8+9 或其他什么。请参阅How do I print an integer in Assembly Level Programming without printf from the c library?,或简化的 2-digit-max 版本。或者如果你动态链接libc,就使用printf,这样它就可以调用自己的init函数。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-02-17
  • 2023-04-02
  • 2021-10-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-07
相关资源
最近更新 更多