【问题标题】:Basics of Assembly programming in 64-bit NASM programming64 位 NASM 编程中的汇编编程基础
【发布时间】:2018-03-28 18:17:44
【问题描述】:

我是汇编编程的新手,并试图解释以下代码,我必须打印 .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. 我被指令弄糊涂了

增加 rsi

据说rsi加1,但是这里的1是什么,bit or byte or 8 byte(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 时,将不会它实际上占用了数组元素大小的两倍到缓冲区中以在转换后存储它?我假设之前的数字需要 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 位数字?还有,为什么?

【问题讨论】:

  • 对于 Stack Overflow 上的一篇帖子来说,这个问题太多了。绝对尝试将每个问题帖子限制为一个问题,最多有一个与主要问题无关的小问题。 How to Ask。不过,您的问题至少相当清晰且易于理解。
  • 好吧,在不同的帖子上添加单独的问题将是一项艰巨的工作,因为它们都与同一个程序相关。
  • 关于 BSS 的问题根本不依赖于 .text 部分中的代码。您可能只是将其作为一个单独的问题提出,也许是一个 2 行示例。 inc rsi 问题再次完全独立于所有周围的代码;这只是关于一条指令本身的问题。对同一个完整程序的不同部分有多个问题并不能使它们相关联。对于 C 语言中的 Hello World,您至少可以提出十几个不同的问题,但这并不意味着它们属于同一个问题。
  • 不会再发生了!!抱歉,我是新手。

标签: assembly 64-bit nasm


【解决方案1】:
  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 点。

【讨论】:

  • 在 5. 你的意思是总是在终端上输出相当于十六进制的 ASCII 码? 7. 反转,因为随着 rsi 增加,它指向 buff 中的更高地址,并且 rbx 的第二次旋转将这个第二高位分配给新增加的 rsi 位置处的位置。因此,存在于较高内存位置的数组元素的数字存在于 buff 中的较低内存位置,并且当我们打印 buff 时,数字被反转打印。如果那是错误的,那么 buff 是如何打印的?即-从较高的内存位置到较低或较低到较高?
  • 咨询ascii table。您发送一个代码,终端显示匹配的字符。 / 像往常一样从低地址打印到高地址。正如预期的那样,低地址具有高位数字。什么都没有逆转。
  • 谢谢!我没有得到 5。完全 - buff 将是数组元素大小的两倍。我认为是的。但如果是这样,那么让我们假设没有。为 0FH 那么它将作为 F00000000H 存储在 buff 中。7 个 30h 将至少存储在内存位置,46h 将存储在最高位置。现在,在打印过程中,将首先打印 30h,依此类推。但是特定的 30h 将如何存储在 buff 中。即 - 作为 03 或 30 以及如何组合表示以使终端知道 30h 是组合而不是孤立的 3h 和 0h ?
  • ascii 使用字节。因此,3003h 不会混淆。您将30h 放入该字节中,这就是终端将使用的内容。
猜你喜欢
  • 2018-09-08
  • 1970-01-01
  • 1970-01-01
  • 2012-05-29
  • 2014-01-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-07
相关资源
最近更新 更多