64 位汇编编程基础 NASM 编程

Basics of Assembly programming in 64-bit NASM programming

我是汇编编程的新手,正在尝试解释以下代码,我必须在其中打印 .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 的最大大小),但是当我在其中输入更多字符时,即使字符串大小超过其最大限制,它仍然会打印整个 msg( 10 个字节).

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

  4. 我对指令感到困惑

inc rsi

据说rsi加1。但是这里的1是什么,bit还是byte还是8byte(rsi的大小)。

  1. 添加 30H 或 37H 会将十六进制数字转换为 39H 或 41H,这些是 9 和 A 在 ASCII 中的十六进制表示,但我不明白为什么打印 39H 或 41H 会产生结果 9 或 A在我的显示器上,而不是 39H 或 41H 本身。是不是无论我们的结果是什么,汇编程序都会在监视器上打印出它的 ASCII 等价物。此外,我们通过 assembler/machine 解释的键盘输入是以什么形式提供的?如果它是 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,因为buff中先存1,后存2。 little endian 和 big endian 在这里存储数字有什么重要性吗?如果是,请解释。

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

  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 点。