64位NASM编程中汇编编程的基础知识

时间:2018-03-28 18:17:44

标签: assembly 64-bit nasm

我是汇编编程的新手,并尝试解释以下代码,我将打印.data部分中的数组: 这是代码:

%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

我有几个问题要问清楚我的怀疑:

  1. .bss部分中存在的变量的默认值是多少?

  2. msg的大小是10个字节(msg的最大大小),但是当我将更多字符放入其中时,即使字符串大小超过其最大限制(10个字节),它仍会打印整个msg。

  3. 如果数组中给出的数字的最后一个(最高有效数字)为非零,则不表示该数字为负数 ie.-数组中11234H不是负数,因为我假设最高有效位在存储器中以1(FFF11234H)存在。我认为对于一个非负数的数字,它的最高位必须为零(011234),这样较高位的位在存储器中存储为0并使数字为正。     如果我在这里错了,那么另外要问的是FFFFFFFFH是-1还是大的正数。

  4. 我对指令感到困惑

  5.   

    inc rsi

    据说rsi增加1.但是这里的1,位或字节或8字节(rsi的大小)是什么。

    1. 添加30H或37H会将十六进制数转换为39H或41H,这些是ASCII中的9和A的十六进制表示,但我不明白为什么打印39H或41H会在我的显示器上产生结果9或A不是39H或41H本身。无论我们的结果如何,汇编程序都会在监视器上打印其ASCII等效项。另外,我们通过汇编器/机器解释的键盘给出的输入是什么形式,如果是ASCII,那么我是否需要将它明确地转换回HEX以便以后计算?

    2. 添加30H或37H后,单位数字(0H-9H或AH-FH)将转换为30H-39H和41H-46H的两位数,因此当我们将其移至buff时,赢得'它实际上占用了数组元素大小的两倍变成buff来转换后存储它吗?我假设前面的数字需要4位,现在转换后需要8位(9h是4位,39h是8位)。如果我错了,请纠正我。 如果我是对的,这就是为什么当每个数组元素大小只有8个字节(四字)时buff被当作16个字节。

    3. 我理解HextoASCII的逻辑,它取数字的最高位并将其存储在buff中,然后继续打印buff,但不会以相反的方式打印数字,因为数字的最高位数是数组元素存储在buff的最低位置,随着rsi递增,下一个数字将被添加到buff的较高位置,因此如果我们打印buff,那么最重要的数字将被放置在buff.ie的最低位置。 -12H在buff中存储为21,因为1首先存储在buff中,然后存储2。这里有小端和大端的重要性来存储数字吗?如果是,请解释。

    4. 在print宏中,第二个参数始终是要打印的变量的大小。这里,buff的大小是16个字节,因此第二个参数是16.但是如果我做第二个参数因为8为什么每个数组元素的一半数字没有被打印,但仍然打印了整个8位数字。另外,给我一个例子,打印出每个数组元素的一半数字,在这种情况下,是打印高位4位还是打印低位4位数?还有,为什么?

1 个答案:

答案 0 :(得分:3)

  1. 零。
  2. 10的大小不是msg。这些只是嵌入式换行。大小计算为len equ $-msg,因此将始终与您提供的文本的长度相匹配。
  3. 根据大小,符号位是最重要的位。由于您有qwords,因此11234H0000000000011234H且为正数。 FFFFFFFFH是一个很大的正数。 FFFFFFFFFFFFFFFFH可能是更大的数字或-1,具体取决于您是将其解释为未签名还是签名。
  4. 没什么,只是1。它只是在rsi中添加一个值。当以后用作地址时,这意味着1个字节。
  5. 这只是因为您的终端使用ascii代码,因此将0打印为值30h(依此类推)。是的,如果您阅读文本,则需要将ascii转换为二进制文件。
  6. 这是对的。
  7. 您正确地描述了它,但这并没有逆转。人类首先从最重要的数字开始。因此,有意义的是,代码首先放置,然后递增rsi以将其他数字放在其后。不确定为什么你认为这是相反的。
  8. 因为分别为每个数组元素调用print,因此缩短输出应用于每个元素而不是整个输出。当然,这将是更高的数字,因为它们是如何在记忆中。见上文第7点。