【问题标题】:NASM Assembly - Get the Result of Multiplying Two Numbers in a LoopNASM 程序集 - 在循环中获取两个数字相乘的结果
【发布时间】:2021-10-14 16:56:07
【问题描述】:

我一直在尝试在循环中获取 2 个数字相乘的结果,但出现此错误:无效的内存引用 (SIGSEGV) 我不知道我做错了什么,一些建议来解决它


;nasm 2.13.02           

section .bss
    result:     resb 2
    num1:       resb 2
    num2:       resb 2
    quotient:   resb 2
    remainder:  resb 2

section .text
    global _start

_start:
    
    ; setup registers
    ; mul -> AX = (AL * BL = AH AL)  The product is in AX. 
                                    ;High-order 8 bits of the product is stored in AH 
                                    ;and the low-order 8 bits are stored in AL.
    mov [num1], word 0x2A     ;store 42 in num1
    mov [num2], word 0x2B     ;store 43 in num2 (42*43=1806)

    mov al, [num1]
    mov bl, [num2]
    mul bl
    
    mov [result], ax
    
    ;call convert_values
    
    ;----------------------------------
    ; divide by ten
    ; div -> AX = (AX(dividendo) / BL(divisor) = AL (Quotient) AH (Remainder))  
                 ;The dividend is assumed to be in the AX register (16 bits). 
                 ;After division, the quotient goes to the AL register and 
                 ;the remainder goes to the AH register. 

    convert_values:
        xor  ax, ax          ; limpiamos el registro AX = 0
        mov  ax, [result]    
        mov  bl, 10          ; 10
        div  bl              ; divide by 10

        mov  [quotient], al  ; save the Quotient 
                
        call print_char      ;print the latest character
       
        mov ax, [quotient]
        mov [result], ax     ;move new number into result                
        
        or  ax,ax            ;set flags based on ax value
        
        jnz  convert_values  ;while ax != 0 continue process
        ret
    
    ; print a character
    print_char:
        mov [remainder], ah        ; gets the Remainder
        add [remainder], word '0'
        mov eax,4                  ; The system call for write (sys_write)
        mov ebx,1                  ; File descriptor 1 - standard output
        mov ecx,remainder          ; Put the offset of remainder in ecx
        mov edx,1                  ; is a constant, so we don't need to say
        int 80h                    ; Call the kernel
        ret
    ;------------------------------------------------
    
    mov eax,1            ; The system call for exit (sys_exit)
    mov ebx,0            ; Exit with return code of 0 (no error)
    int 80h;

【问题讨论】:

  • 可能不是您崩溃的原因,但是您的变量有很多字节和字访问混合,这可能会在修复崩溃后给您错误的答案。例如num1 是一个字(两个字节),但由于al 是一个字节寄存器,mov al, [num1] 只加载该字的低字节。我建议检查对变量的所有引用以了解正确的操作数大小。
  • convert_values 最后有一个ret,但它没有被call 调用,所以这将跳转到堆栈外的一个随机地址,并且可能会出现段错误。跟踪控制流向何处,并确保它在您的退出系统调用(当前无法访问)时结束。

标签: nasm


【解决方案1】:

这是一个更新,我修复了它。 :)


;nasm 2.13.02           

section .bss
    result:     resb 2
    num1:       resb 2
    num2:       resb 2
    quotient:   resb 2
    remainder:  resb 2

section .text
    global _start

_start:
    
    ; setup registers
    ; mul -> AX = (AX * BX = DX BX)  
                                    ;The multiplicand should be in the AX register, 
                                    ;and the multiplier is a word in memory or another register. 
                                    ;For example, for an instruction like MUL DX, 
                                    ;you must store the multiplier in DX and the multiplicand in AX.

                                    ;The resultant product is a doubleword, which will need 
                                    ;two registers. The high-order (leftmost) portion gets stored 
                                    ;in DX and the lower-order (rightmost) portion gets stored 
                                    ;in AX.
    
    mov [num1], word 0x2A     ;store 42 in eax
    mov [num2], word 0x2B     ;store 43 in edx (42*43=1806)

    mov ax, [num1]
    mov bx, [num2]
    mul bx
    
    mov [result], ax
    
    call convert_values
    
    ;----------------------------------
    ; divide by ten
    ; div -> AX = (AX(dividendo) / BL(divisor) = AL (Quotient) AH (Remainder))  
                 ;The dividend is assumed to be in the AX register (16 bits). 
                 ;After division, the quotient goes to the AL register and 
                 ;the remainder goes to the AH register. 
    convert_values:
        xor  ax, ax           ; clears AX register to `0`
        mov  ax, [result]    
        mov  bl, 10           ; 10
        div  bl               ; divide por 10

        mov  [quotient], al   ; save the Quotient 
                
        call print_char       ;print the latest character
       
        mov  ax, [quotient]   ;move `Quotient` to AX register
        test ax,ax            ;Compares if AX register is equal to `0`
        jz   exit;            ;if flag `ZF` is equal to `1` jump to `exit` label
        
        mov [result], ax      ;moves data from AX register to `result`            
        
        cmp ax,0              ;set flags based on ax value
        
        jnz  convert_values  ;while al != 0 continue process
        ret
    
    ; print a character
    print_char:
        mov [remainder], ah        ; gets the Remainder
        add [remainder], word '0'
        mov eax,4                  ; The system call for write (sys_write)
        mov ebx,1                  ; File descriptor 1 - standard output
        mov ecx,remainder          ; Put the offset of hello in ecx
        mov edx,1                  ; is a constant, so we don't need to say
        int 80h                    ; Call the kernel
        ret
    ;---------------------------------------------
    exit:
        mov eax,1            ; The system call for exit (sys_exit)
        mov ebx,0            ; Exit with return code of 0 (no error)
        int 80h;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多