将值插入数组并显示,nasm

时间:2017-11-10 22:30:09

标签: arrays ubuntu assembly x86 nasm

首先,这是一项家庭作业。

我有一个循环来分别得到两位数的值,并通过将第一个数字乘以10并加上第二个数字来得到一个整数来加入它们。

我正在做所有这些并保存在我的AL寄存器中,现在我想将该整数插入到数组中,然后扫描该数组并显示这些数字。

如何插入载体并从载体中读取?

我的阵列:

section .bss
    array resb 200  

我的数字转换:

sub byte[digit_une], 30h
sub byte[digit_two], 30h

mov al, byte[digit_one]         
mov dl, 10                  ;dl = 10
mul dl                      ;al = ax = 10 * digit_one
add al, byte[digit_two]     ;al = al + digit_two = digit_one * 10 + digit_two

1 个答案:

答案 0 :(得分:2)

“数组”,“向量”等......所有这些都是更高层次的概念。机器有内存,可以通过单字节寻址,你用你的代码实现什么样的逻辑,这取决于你。但你应该能够在两个层面上考虑它,作为内存中的单个字节,每个都拥有自己的地址,并完全理解你的代码逻辑,它将如何安排使用这些字节来形成“某种数组”。

根据您对.bss扇区的定义,您可以定义一个符号/标签array,它等于.bss段开始的内存地址。然后你保留200个字节的空间,所以你要添加的任何其他东西(比如另一个标签)将从地址.bss+200开始。

让我们说(例如)在将二进制文件加载到内存并跳转到入口点之后,.bss位于地址0x1000

然后

mov dword [array],0x12345678

将4个字节存储在地址0x1000 .. 0x1003的内存中,特定字节的值为78 56 34 12(该dword值的little-endian分解)。

如果您将执行mov dword [array+199],0x12345678,您将在0x78的最后一个正式保留字节中写入值resb 200,其余3个字节将覆盖地址处的内存.bss + 200 ,.bss + 201和.bss + 202(可能会破坏其他一些数据,如果你在那里放东西,或者你的应用程序崩溃,如果它会穿过内存页面边界,那么你的进程可用内存已经结束了)。

由于您希望将N 字节值存储到数组中,最简单的逻辑是将第一个值存储在地址array+0中,将第二个值存储在array+1等等...(对于 dword 值,最合乎逻辑的方式是array+0, array+4, array+8, ....)。

即。 mov [array+0],al可用于存储第一个值。但是,如果您正在以某种循环方式读取输入,那么这不太实际。假设您想要从用户那里读取最多200个值,或者值99将更快结束,那么您可以通过寄存器使用索引,例如:

    xor esi,esi  ; rsi = index = 0
    mov ecx,200  ; rcx = 200 (max inputs)
input_loop:

    ; do input into AL = 0..99 integer (preserve RSI and RCX!)
    ...

    cmp al,99
    je  input_loop_terminate
    mov [array+rsi], al   ; store the new value into array
    inc rsi      ; ++index
    dec rcx      ; --counter
    jnz input_loop   ; loop until counter is zero
input_loop_terminate:
    ; here RSI contains number of inputted values
    ; and memory from address array contains byte values (w/o the 99)

即。对于用户输入32,72,13,0,16,99,地址0x1000处的存储器将修改5个字节,包含(现在为六进制):20 48 0D 00 10 ?? ?? ?? ...

如果你是熟练的asm程序员,你不仅会通过寄存器进行索引,还会避免硬编码的array标签,所以你可能会做一个子程序,它接受作为参数目标地址(数组),以及最大数量:

; function to read user input, rsi = array address, rcx = max count
; does modify many other registers
; returns amount of inputted values in rax
take_some_byte_values_from_user:
    jrcxz .error_zero_max_count  ; validate count argument
    lea rdi,[rsi+rcx]  ; rdi = address of first byte beyond buffer
    neg rcx            ; rcx = -count  (!)
      ; ^ small trick to make counter work also as index
      ; the index values will be: -200, -199, -198, ...
      ; and that's perfect for that "address of byte beyond buffer"
.input_loop:

    ; do input into AL = 0..99 integer (preserve RSI, RDI and RCX!)
    ...

    cmp al,99
    je  .input_loop_terminate
    mov [rdi+rcx], al  ; store the new value into array
    inc rcx            ; ++counter (and index)
    jnz .input_loop    ; loop until counter is zero
.input_loop_terminate:
    ; calculate inputted size into RAX
    lea rax,[rdi+rcx]  ; address beyond last written value
    sub rax,rsi        ; rax = count of inputted values
    ret

.error_zero_max_count:
    xor eax,eax        ; rax = 0, zero values were read
    ret

然后你可以从主代码中调用那个子程序:

    ...
    mov   rsi,array    ; rsi = address of reserved memory for data
    mov   ecx,200      ; rcx = max values count
    call  take_some_byte_values_from_user
    ; keep RAX (array.length = "0..200" value) somewhere
    test  al,al        ; as 200 was max, testing only 8 bits is OK
    jz    no_input_from_user  ; zero values were entered
    ...

对于word / dword / qword元素数组,x86在内存操作数中有缩放因子,因此你可以使用+1的索引值和地址值,如:

    mov   [array+4*rsi],eax  ; store dword value into "array[rsi]"

对于其他大小的元素,通常使用指针而不是索引更有效,并通过像add <pointer_reg>, <size_of_element>这样的add rdi,96移动到下一个元素,以避免每次访问的索引值相乘。

等......读回值的方式也是一样的,但是反转了操作数。

顺便说一句,这些例子并没有像在数据中“覆盖”那么多“插入”值。计算机内存已经存在并有一些值(.bss被libc或OS IIRC归零?否则可能会有一些垃圾),所以它只是用来自用户的值覆盖旧的垃圾值。 resb仍有200个字节的内存“保留”,您的代码必须跟踪实际大小(输入值的计数)才能知道,用户输入的结束位置以及垃圾数据的开始位置(或者最终可能也将99值写入数组,并将其用作“终结符”值,然后只需要数组地址来扫描内容,并在找到值99时停止。

编辑:

如果您仍然想知道为什么我有时使用方括号而有时不使用方括号,这个Q + A看起来足够详细,YASM语法与括号用法中的NASM相同:Basic use of immediates (square brackets) in x86 Assembly and yasm