简体   繁体   中英

Basics of Assembly programming in 64-bit NASM programming

I am new to assembly programming and trying to interpret the following code where I've to print an array present in the .data section : Here is the code:

%macro print 2
    mov rax,1
    mov rdi,1
    mov rsi,%1
    mov rdx,%2
    syscall
%endmacro

%macro exit 0
    mov rax,60
    mov rdi,0
    syscall
%endmacro


section .data

    msg db 10,"Array is : ",10
    len equ $-msg   

    array dq 11234H, 0AB32H, -3326H, 056BH

    newline db 10

section .bss

    buff resb 16;

section .code
global _start
_start:
    print msg,len
    mov rsi,array
    mov rcx,4
    back:
        mov rbx,[rsi]
        push rsi
        push rcx
        call HextoASCII
        print newline,1
        pop rcx
        pop rsi
        add rsi,8
    loop back

    exit


HextoASCII:
    mov rsi,buff
    mov rcx,16
    back1:
        rol rbx,4
        mov al,bl
        and al,0fh
        cmp al,9h
        jbe add_30h
        add al,7h
        add_30h:
            add al,30h

        mov [rsi],al
        inc rsi
    loop back1
    print buff,16
ret

I have a few questions to ask to clear my doubts :

  1. What is the default value of the variable present in the .bss section ?

  2. The size of msg is 10 bytes(max size of msg), but when I put more characters into it, then it still prints the entire msg even though the string size exceeds its maximum limit(10 bytes).

  3. If the numbers given in the array have their last(highest significant digit) as non-zero, doesn't it mean that the number is negative ie.- Isn't 11234H present in the array a negative number because I assume that the highest significant bits are present as 1 (FFF11234H) in the memory. I think that for a number to be non-negative its highest digit must be zero(011234), so that the higher ordered bits are stored as 0 in memory and make the number positive. If I'm wrong here then another thing to ask is whether FFFFFFFFH is -1 or a large positive number.

  4. I am getting confused by the instruction

inc rsi

It is said that rsi is incremented by 1. But what is 1 here,bit or byte or 8 byte(size of rsi).

  1. Adding 30H or 37H converts the hexadecimal digit to 39H or 41H and these are hexadecimal representation of 9 and A in ASCII but I do not understand why printing 39H or 41H will yield the result 9 or A on my monitor and not 39H or 41H itself. Is it that whatever our result is, the assembler prints its ASCII equivalent on the monitor. Also, In what form is the input that we give through keyboard interpreted by assembler/machine and if it is ASCII then do I need to convert it back to HEX explicitly for later calculations ?

  2. After adding 30H or 37H,the single digit number(0H-9H or AH-FH) gets converted into double digit ranging from 30H-39H and 41H - 46H and so when we move this to buff, won't it actually occupy double the size of array element into buff to store it after the conversion ? I assume that earlier the digit took 4 bits and now it takes 8 bit after the conversion(9h is 4 bit and 39h is 8 bit). Do correct me, if I'm wrong here. If I'm right then, Is that the reason why buff is taken as 16 bytes when each array element size is just 8 bytes(quadword).

  3. I understand the logic of HextoASCII which takes the highest digit of the number and stores it in buff and this goes on and later buff is printed but won't the number be printed in reverse manner because the highest digit of array element be stored at the least significant location of buff and as rsi is incremented the next digit will be added at the higher position of buff and so if we print buff then the most significant number gets placed at the least significant location of buff.ie-12H is store as 21 in buff because 1 is stored first in buff and later 2 is stored. Is there any importance of little endian and big endian here to store the digits ? Do explain, if yes.

  4. In the print macro, 2nd argument is always the size of the variable that is to be printed.Here, the size of buff is 16 bytes and hence the second argument is 16. But if I make the 2nd argument as 8 then why is half of the digits of every array element not being printed but still the entire 8 digits are getting printed. Also, present me a case where half of the digits of every element of array will be printed, In that case will the higher significant 4 digits be printed or the lower significant 4 digits be printed ? Also, why ?

  1. Zero.
  2. 10 is not the size of msg . Those are just embedded line feeds. The size is calculated as len equ $-msg and thus will always match the length of the text you provide.
  3. The sign bit is the most significant bit according to the size. Since you have qwords, 11234H is 0000000000011234H and is positive. FFFFFFFFH is a large positive number. FFFFFFFFFFFFFFFFH could be an even larger number or -1 , depending on whether you interpret it as unsigned or signed.
  4. Nothing, it's just 1 . It's just adding one to the value in rsi . That will mean 1 byte when used as an address later.
  5. That's just because your terminal uses ascii codes and hence will print 0 for a value of 30h (and so on). Yes, you will need to convert from ascii to binary if you read text.
  6. That is correct.
  7. You described it correctly, but that is not reversed. Humans start with the most significant digit first. So it makes sense that the code puts that first and increments rsi to put the other digits after it. Not sure why you think that is reversed.
  8. Because print is invoked for each array element separately, hence shortening the output applies to each element not to the whole output. It will be the higher digits of course, since that's how they are in memory. See point 7, above.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM