Multiplying two values and printing them to the screen (NASM, Linux)

前端 未结 1 644
没有蜡笔的小新
没有蜡笔的小新 2020-12-20 04:47

I keep reading that in order for one to perform integer/floating point division on a register, the register(s) being performed on need to actually be initialized

相关标签:
1条回答
  • 2020-12-20 05:11

    We spoke separately in chat....

    Here's a working version to play with.

    It has a subtle problem. Can you find it? Can you explain WHY it does what it does?

    ; Multiply two numbers, display in ascii/decimal
    ;
    ; (because I have a 64bit system, this forces 32bit code)
            bits    32
    ;
            section .text
    ;
    ; _start is the ONLY label you MUST prepend _
    ; others might be library functions (ex: _printf,_exit)
    ; pure assembly only needs _start, if linked with glibc
    ; typically need _main INSTEAD of _start
    ;
            global _start
    ;
    ;
    _start:
            nop                             ;placeholder for gdb's debug interrupt
    ;
            call    mul                     ;multiply the values
            call    convert_values          ;do hex to ascii conversion
    ;
            jmp     safe_exit               ;use jmp as opposed to call since it technically doesn't 'ret'
    ;
    ;
    ; subroutines / functions follow
    ;
    mul:
            mov     eax, 0x2A               ;store 42 in eax
            mov     edx, 0x2B               ;store 43 in edx (42*43=1806)
            mul     edx                     ;multiply eax*edx, result in edx:eax
            ret
    ;
    ; this routine doesn't handle BIG values from 'mul' which extend into edx
    ; we're learning, don't make things multiply out to more than 4.2 billion-ish
    convert_values:
            mov     edx,0                   ;value actually edx:eax, zero edx
            mov     ecx,0x0A                ;divide edx:eax by 10
            idiv    ecx                     ;result in eax, remainder in edx
            push    eax                     ;save value on stack
            mov     eax,edx                 ;put remainder (0-9) in eax
            add     eax,'0'                 ;convert value to ascii character
            call    print_char              ;print the latest character
            pop     eax                     ;restore value
            or      eax,eax                 ;set flags based on eax value
            jnz     convert_values          ;while eax != 0 continue process
    ;
    ; nasm doesn't convert \n into LF... just use 10, equivalent
    endl:
            mov     eax, 10                 ;store newline character in eax to be printed
            call    print_char              ;print value
            ret
    ;
    print_char:
            mov     [valueToPrint], eax     ;store contents of 'eax' in [valueToPrint]
            mov     eax, 4                  ;syswrite
            mov     ebx, 1                  ;stdout
            mov     ecx, valueToPrint       ;machine will take whatever value exists in [ecx] and print
            mov     edx, 1                  ;print only a single byte's worth of data
            int     0x80                    ;invoke kernel to perfrom instruction
            ret
    ;
    safe_exit:
            mov     eax,1                   ;initiate 'exit' syscall
            mov     ebx,0                   ;exit with error code 0
            int     0x80                    ;invoke kernel to do its bidding
    ;
    ; =====================================
            section .bss
    ; this section is not allocated, just reserved.
    ; Automatically set to zero when program starts
    ;
    ; alloc 4 bytes of data in 'valueToPrint'
    valueToPrint:
            resd    1               ; 1 resd=4 resb (Dword/Byte)
    ;
    ;
    

    Spoiler Alert...

    It prints the result BACKWARDS!
    To fix this, we'll have to redesign how the digits are obtained and stored before printing.

    I'm emailing this directly to you, along with some additional notes.

    0 讨论(0)
提交回复
热议问题