代码之家  ›  专栏  ›  技术社区  ›  asn

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

  •  0
  • asn  · 技术社区  · 7 年前

    我是汇编编程新手,试图解释以下代码,其中我必须打印中存在的数组。数据部分: 代码如下:

    %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. 消息的大小是10字节(最大消息大小),但当我在其中输入更多字符时,即使字符串大小超过其最大限制(10字节),它仍会打印整个消息。

    3. 如果数组中给出的数字的最后一位(最高有效位)为非零,这不意味着该数字为负吗 ie.-数组中存在的11234H不是负数吗?因为我假设最高有效位在内存中以1(FFF11234H)的形式存在。我认为,要使一个数字非负,其最高位数必须为零(011234),这样更高阶的位在内存中存储为0,并使数字为正。 如果我在这里错了,那么另一个问题是ffffffffffh是-1还是一个大的正数。

    4. 我被这个指示弄糊涂了

    公司rsi

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

    1. 添加30H或37H将十六进制数字转换为39H或41H,这是ASCII中9和A的十六进制表示,但我不明白为什么在我的显示器上打印39H或41H会产生结果9或A,而不是39H或41H本身。不管我们的结果是什么,汇编程序都会在监视器上打印其ASCII等价物。此外,我们通过键盘提供的输入是以什么形式由汇编器/机器解释的,如果是ASCII,那么我是否需要显式地将其转换回十六进制以供以后的计算?

    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. 在打印宏中,第二个参数始终是要打印的变量的大小。这里,buff的大小是16个字节,因此第二个参数是16。但是如果我把第二个参数设为8,那么为什么每个数组元素的一半数字没有被打印出来,而整个8个数字仍然被打印出来。另外,请给我一个例子,其中数组每个元素的一半数字将被打印,在这种情况下,将打印较高有效的4位数字,还是打印较低有效的4位数字?还有,为什么?

    1 回复  |  直到 7 年前
        1
  •  3
  •   Jester    7 年前
    1. 10 不是的大小 msg 。这些只是嵌入的换行符。大小计算如下 len equ $-msg 因此,它将始终与您提供的文本长度相匹配。
    2. 根据大小,符号位是最重要的位。既然你有qwords, 11234H 0000000000011234H 而且是积极的。 FFFFFFFFH 是一个很大的正数。 FFFFFFFFFFFFFFFFH 可能是更大的数字或 -1 ,这取决于您是将其解释为未签名还是已签名。
    3. 没什么,只是 1 。它只是在 rsi 。当以后用作地址时,这意味着1个字节。
    4. 这只是因为您的终端使用ascii码,因此将打印 0 对于值 30h (等等)。是的,如果您阅读文本,则需要将ascii转换为二进制。
    5. 这是正确的。
    6. 你描述得很对,但事实并非如此。人类首先从最重要的数字开始。因此,代码将其放在第一位并递增是有意义的 rsi指数 把其他数字放在后面。不知道为什么你会认为这是相反的。
    7. 因为 print 分别为每个数组元素调用,因此缩短了应用于每个元素而不是整个输出的输出。当然是更高的数字,因为它们在内存中是这样的。见上文第7点。