发布于 2026-01-06 0 阅读
0

x86 汇编语言数组

x86 汇编语言数组

最近编写了6 个关于 x86 的 x86 组件的传奇故事,并考虑了计算机架构和程序的低级设计,涉及极简多线程 Web 服务器。

在整个过程中,阿卡贝·德·拉多·阿尔贡斯(Lado Alguns)对后部重要的事情感到满意,在传奇故事中,我要注意的是,我最重要的是。考虑到这一点,我们可以通过线程池来实现。

如果文件已被删除,则不可避免地会删除数组并组织计算机的内存。

在此过程中,您可以了解内存操作、注册器和内存堆的基本原理,并长期实现数组。

您可以使用熟悉的 x86 和 GDB 组件。 Caso não tenha,推荐加强休闲传奇。


议程


数组不存在

数组不存在。简单的阿西姆。

Como vimos naparte IV da saga,一个关于连续形式的记忆和组织,作为外文的信息。

memoria é contígua

声明以下信息的后续序列:



1, 2, 'H', 0


Enter fullscreen mode Exit fullscreen mode

Eu sei,eu sei,os Tipos estão Misturados,mas isto não importa para este momento。全部内容 1 字节

Em assembly x86(vamos chamar de asm no Restante do artigo),podemos 声明了以下信息:



section .data
stuff: db 0x1, 0x2, 0x48, 0x0


Enter fullscreen mode Exit fullscreen mode

Lembrando que o 字符 'H' na tabela ASCII 表示 0x48 em 十六进制

为了方便gdb调试,可以确认十六进制的顺序,而不是顺序排列的顺序stuff



# Leitura do primeiro hexabyte em stuff
(gdb) x/1xb (void*) &stuff
0x402000 <stuff>:       0x01

# Leitura do segundo hexabyte em stuff
(gdb) x/1xb (void*) &stuff+1
0x402001:       0x02

# Leitura do terceiro hexabyte em stuff
(gdb) x/1xb (void*) &stuff+2
0x402002:       0x48


Enter fullscreen mode Exit fullscreen mode

0x48使用字符串格式表示十六进制的 Podemos tambémx/s



(gdb) x/s (void*) &stuff+2
0x402002:       "H"


Enter fullscreen mode Exit fullscreen mode

É tudo hexadecimal!

com isto,caso queiramos 表示字符串“Hello”,de acordo com 表示 tabela ASCII,poderia ficar assim:



section .data
msg: db 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x0


Enter fullscreen mode Exit fullscreen mode

没有 gdb vamos 验证代表字符串的规则msg



(gdb) x/s &msg
0x402000 <msg>: "Hello"


Enter fullscreen mode Exit fullscreen mode

Em asm, é possível declarar a string já com a representação dieta da tabelas ASCII:



section .data
msg: db "Hello", 0x0

; é o mesmo que
; msg: db 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x0


Enter fullscreen mode Exit fullscreen mode

Strings também não existem

您可以使用十六进制的内存。嗯,数组,assim 和字符串,是一个简单的序列,用于存储内存中的数据。

字符串与“特殊数组”不同,它们代表 ASCII 字符(注意,字符串和数组的终止符代表字节“最终”):

字符串数组

O 数组可能很简单

接下来是一个简单的数组实现,我们将继续探索后续的过程:



global _start

%define SYS_exit 60
%define EXIT_SUCCESS 0

section .data
array: db 1, 2, 3, 0

section .text
_start:
    mov al, [array]        ; array[0]
    mov bl, [array + 1]    ; array[1]
    mov cl, [array + 2]    ; array[2]
    mov sil, [array + 3]   ; array[3]
.exit:
    mov rdi, EXIT_SUCCESS
    mov rax, SYS_exit
    syscall


Enter fullscreen mode Exit fullscreen mode

在初始化时.data,声明 um 数组为 1 字节 cada 的 3 个元素(inteiros de 1 a 3),使用数字 0 来作为数组的终点:



section .data
array: db 1, 2, 3, 0


Enter fullscreen mode Exit fullscreen mode

接下来,.text程序的源代码、使用方法、配置或注册者结果的数组元素的获取方式如下:



section .text
_start:
mov al, [array]        ; array[0]


Enter fullscreen mode Exit fullscreen mode

如果没有注册器 (AL) 的记录和配置或结果,则无法继续升级0x402000或继续使用 1 字节的注册器,否则,将无法配置存储和配置的注册器或初始字节数组。

Vamos conferir com gdb:



# O array está armazenado no endereço 0x402000
# e contém o valor em hexa 0x00 0x03 0x02 0x01,
# lembrando que esta arquitetura utiliza o formato little-endian
(gdb) x &array
0x402000 <array>:       0x00030201

(gdb) b 13
(gdb) run
(gdb) next

# No registrador AL temos o primeiro elemento do array
(gdb) i r al
al             0x1                 1

# É o mesmo que acessar o primeiro hexabyte contido no endereço
# 0x402000
(gdb) x/1xb 0x402000
0x402000 <array>:       0x01



Enter fullscreen mode Exit fullscreen mode

Lembrando 是注册器 AL 代表 8 位注册器 RAX 的主要概念,是 x86_64 架构中的 64 位总数

数组中的元素的扩展、连接器的排列和 1 字节注册器的配置:



mov al, [array]        ; array[0] => 1
mov bl, [array + 1]    ; array[1] => 2
mov cl, [array + 2]    ; array[2] => 3
mov sil, [array + 3]   ; array[3] => 0 (aqui termina o array)


Enter fullscreen mode Exit fullscreen mode

使用数组而不是初始化

在集市上,我们声明了以下内容.data并进行了初始化。启动恐龙”程序,声明一系列未初始化的数据。.bss

前面的示例中,我们声明了 4 个字节的数组,使用了resb“保留字节”指令,其中 3 个字节是数组元素的保留,并且用字节表示 0x0 来表示数组的终止符。



section .bss
array: resb 4 ; 3 bytes + 1 byte de término


Enter fullscreen mode Exit fullscreen mode

没有 gdb,数组初始值是 0,指示值是 4 字节保留值:



(gdb) x &array
0x402004 <array>:       0x00000000

(gdb) x/4xb &array
0x402004 <array>:       0x00    0x00    0x00    0x00


Enter fullscreen mode Exit fullscreen mode

没有任何其他的元素,请注意使用一些技巧,所有这些都不是在初始阶段之前的示例。



; Move o valor 1 para o primeiro byte do endereço de memória em array
mov byte [array], 1  ; array[0] = 1


Enter fullscreen mode Exit fullscreen mode

Com gdb 确认没有渲染 0x402000 是数组,请注意字节 1:



(gdb) x &array
0x402000 <array>:       0x00000001


Enter fullscreen mode Exit fullscreen mode

E se quisermos adicionar or valor 2 no próximo byte do array?



mov byte [array + 1], 2


Enter fullscreen mode Exit fullscreen mode


(gdb) x &array
0x402000 <array>:       0x00000201


Enter fullscreen mode Exit fullscreen mode

修复数组中的“索引”修改。在数组的初始位置,使用索引 0,在后续位置,使用索引 1,在终点数组上递增。

Seria muito complicado ficar manipulando índice 硬编码。 Precisamos de um ponteiro pararepresentar este índice。

Índice para o resgate

假设数组已为零,并在数组上存储内存,则声明以下内容.data



section .bss
array: resb 4 ; 3 bytes + 1 byte de término

section .data
pointer: db 0


Enter fullscreen mode Exit fullscreen mode

徽标、其他主要元素以及接下来的形式,请参阅?



mov byte [array + pointer], 1   ; array + 0


Enter fullscreen mode Exit fullscreen mode

Ao rodar o programa, temos o seguinte erro:



src/live.asm:14: error: invalid effective address: multiple base segments


Enter fullscreen mode Exit fullscreen mode

这可能会导致操作多个内存段的部分的错误,而不是数组和指针。

Para resolver isto, precisamos fazer manipulação de ponteiros com valores imediatos (que foi o caso anterior com número hard-coded) or com registradores:



; append(1)
mov al, byte [pointer]
mov byte [array + rax], 1   ; array + 0


Enter fullscreen mode Exit fullscreen mode
  • 初始指令移动初始字节连续,没有渲染pointer和设备没有注册器 AL
  • 第二个指令是移动 valor imediato 1(数组元素)以渲染数组内存。对于 RAX(AL 版本的 64 位)来说,它0x0代表了一种能力,它可以插入到数组中的原始字节中

E para armazenar o segundo elemento no array?



; append(2)
mov al, byte [pointer]
mov byte [array + rax], 2


Enter fullscreen mode Exit fullscreen mode

没有 gdb,vamos 验证了以下内容:



(gdb) x &array
0x402004 <array>:       0x00000002


Enter fullscreen mode Exit fullscreen mode

呃,哦…… Desta forma estamos sobrescrevendo o valor front。 Queremos na verdade que o ponteiro "ande", ou seja, precisa ser Incrementado em um byte para que o append(2)resulte com os 2 elementos no array.

请参阅INC解决此问题的说明:



mov al, byte [pointer]      ; pointer -> 0
mov byte [array + rax], 1   ; array + 0
inc byte [pointer]          ; pointer -> 1

mov al, byte [pointer]
mov byte [array + rax], 2   ; array + 1


Enter fullscreen mode Exit fullscreen mode


(gdb) x &array
0x402004 <array>:       0x00000201


Enter fullscreen mode Exit fullscreen mode

耶! Que dia maravilhoso!

Atingindo o limite do array

是否可以连续增加或限制阵列?



mov al, byte [pointer]
mov byte [array + rax], 1   ; array + 0
inc byte [pointer]

mov al, byte [pointer]
mov byte [array + rax], 2   ; array + 1
inc byte [pointer]

mov al, byte [pointer]
mov byte [array + rax], 3   ; array + 2
inc byte [pointer]


Enter fullscreen mode Exit fullscreen mode


# Lendo os primeiros 4 hexabytes do array, temos a representação
# do array cheio com todos os espaços ocupados, lembrando que
# o último byte é o término do array
(gdb) x /4xb &array
0x402004 <array>:       0x01    0x02    0x03    0x00

# O ponteiro está no fim do array
(gdb) x &pointer
0x402000 <pointer>:     0x03


Enter fullscreen mode Exit fullscreen mode

Maravilha,e se adicionar mais um elemento,nossoprograma deveria allowedir?



mov al, byte [pointer]
mov byte [array + rax], 4   ; array + 3
inc byte [pointer]


Enter fullscreen mode Exit fullscreen mode


# Não deveríamos permitir que mais um elemento fosse adicionado,
# pois nosso array já estava cheio
(gdb) x /4xb &array
0x402004 <array>:       0x01    0x02    0x03    0x04

# O ponteiro está para além da capacidade array (not good...)
(gdb) x &pointer
0x402000 <pointer>:     0x04


Enter fullscreen mode Exit fullscreen mode

Vamos utilizar um Jump condicional (explico mais sobre isto na saga ) para não allowedir que o elemento seja adicionado.如果不添加数组,请先验证是否不添加数组:



cmp byte [pointer], 3   ; verifica se o array está cheio
je .exit                ; salta para a rotina .exit caso a flag seja levantada


Enter fullscreen mode Exit fullscreen mode

Assim fica 或完整程序:



global _start

%define SYS_exit 60
%define EXIT_SUCCESS 0

section .bss
array: resb 4 ; 3 bytes + 1 byte de término

section .data
pointer: db 0

section .text
_start:
    cmp byte [pointer], 3   ; verifica se o array está cheio
    je .exit

    mov al, byte [pointer]
    mov byte [array + rax], 1   ; array + 0
    inc byte [pointer]

    cmp byte [pointer], 3   ; verifica se o array está cheio
    je .exit

    mov al, byte [pointer]
    mov byte [array + rax], 2   ; array + 1
    inc byte [pointer]

    cmp byte [pointer], 3   ; verifica se o array está cheio
    je .exit

    mov al, byte [pointer]
    mov byte [array + rax], 3   ; array + 2
    inc byte [pointer]

    cmp byte [pointer], 3   ; verifica se o array está cheio
    je .exit

    ; não deveria permitir adicionar o quarto elemento,
    ; pois o array suporta até 3 elementos. desta forma,
    ; estaríamos escrevendo no endereço de memória de outros
    ; dados do programa
    mov al, byte [pointer]
    mov byte [array + rax], 4   ; array + 3
    inc byte [pointer]
.exit:
    mov rdi, EXIT_SUCCESS
    mov rax, SYS_exit
    syscall


Enter fullscreen mode Exit fullscreen mode


(gdb) x &pointer
0x402000 <pointer>:     0x00000003
(gdb) x &array
0x402004 <array>:       0x00030201


Enter fullscreen mode Exit fullscreen mode

Perfeito, vamos agora fazer um pequeno refactoring no código separando a lógica de appara uma subrotina:



global _start

%define SYS_exit 60
%define EXIT_SUCCESS 0
%define CAPACITY 3

section .bss
array: resb CAPACITY + 1

section .data
pointer: db 0

section .text
_start:
    mov rdi, 1
    call .append

    mov rdi, 2
    call .append

    mov rdi, 3
    call .append

    mov rdi, 4
    call .append
.exit:
    mov rdi, EXIT_SUCCESS
    mov rax, SYS_exit
    syscall
.append:
    cmp byte [pointer], CAPACITY ; verifica se o array está cheio
    je .done

    mov al, byte [pointer]
    mov byte [array + rax], dil
    inc byte [pointer]
.done:
    ret


Enter fullscreen mode Exit fullscreen mode

Se você quer entender mais sobre 条件跳转、 rotinas、 call、 ret e flags、 sugiro a leitura da minha saga que foi Referenciada diversas vezes Neste artigo

Executando com gdb e...



(gdb) x &array
0x402004 <array>:       0x00030201

(gdb) x &pointer
0x402000 <pointer>:     0x00000003


Enter fullscreen mode Exit fullscreen mode

太棒了!

进入游戏后,我们需要重新调整数组以支持更多要素,或者进行一些动态调整。

是否有其他一些基本要素可以在记忆以外的区域中获得,但不能在数组中找到?


堆,堆,好耶!

堆中的元素与计算机程序内存的布局有关:

内存布局

  • 布局和表示计算机内存中的内存的渲染效果主要取决于直接编程的效果
  • 记住所有的信息,接下来的内容.text,以及有关程序的参考信息
  • 您可以在以下内容中了解我们所考虑的初始信息.data以及所代表的信息的后续内容.bss
  • 程序的主要内容、程序的堆栈、程序的参数、程序的名称、参数和程序的信息,以解决堆栈中的问题,并且可以从功能和参数方面来了解程序的信息。
  • 堆栈的格式和“cresce pra baixo”,或者,符合堆栈中的元素,直接在内存中增加cresce

没有“meio”进行布局,进入堆栈的一部分,整个内存空间与相关。没有堆,从动态角度看,与动态角度不同。

Para acomodar um array de tamanho dinâmico que support redimensionamento (resize), temos de alocar memória nesta área.

接下来,我们将在堆栈中存储一些内存

Alocação dinâmica de memória com brk

通过操作该存储器和系统调用的格式可以中断程序,然后终止数据

节目插播

com brk,可以修改某些程序,以实现更高的效果,或者允许对程序和文件夹中的内存区域进行操作。

程序中断可视化

首先,请先执行以下操作: 映射系统调用,然后执行以下操作:



%define SYS_brk 12
....

section .text
_start:
; syscall para acessar o program break (0x403000), que é onde termina 
; a seção de dados e começa o heap
mov rdi, 0
mov rax, SYS_brk
syscall
....


Enter fullscreen mode Exit fullscreen mode

Com gdb、vamos analisar 或 estado do 程序:



# Breakpoint na linha da syscall brk
(gdb) b 18
(gdb) run

# O início do programa fica na seção .text e começa com 
# 0x401000
(gdb) x _start
0x401000 <_start>:      0x000000bf

# O pointer está na seção .data um pouco mais acima e começa com
# 0x402000
(gdb) x &pointer
0x402000 <pointer>:     0x00000000

# O array está na seção .bss um pouco mais acima e começa com 
# 0x402004
(gdb) x &array
0x402004 <array>:       0x00000000

# Executa a syscall brk
(gdb) n

# A syscall brk armazena em RAX o endereço de memória do program break, 
# no caso um pouco mais acima em 0x403000
(gdb) i r rax
rax            0x403000            4206592


Enter fullscreen mode Exit fullscreen mode
  • 0x401000:.text接下来是节目内容
  • 0x402000:.data以下内容为初始信息
  • 0x402004:.bss接下来的内容
  • 0x403000: 程序中断,然后终止在“堆”部分

这是一个在数组元素上渲染的部分0x403000,使用字节来渲染数组,在没有堆的情况下渲染数组元素。

数组无堆

Na syscall que fizemos, se o argumento em RDI tiver zero,significa que brk vai retornar o program break atual, no caso 0x403000.可以通过系统调用 brk com 或 RDI 不同的参数(增量)来解决程序中断问题。

市场上的一部分,在数组中.bss,最多可以保留 4 字节数组,需要 1 字节代表数组内存的存储:



global _start

%define SYS_brk 12
%define SYS_exit 60
%define EXIT_SUCCESS 0
%define CAPACITY 3

; inicialmente começa com 0x000000, mas depois irá conter 
; o endereço 0x403000
section .bss
array: resb 1  

section .data
pointer: db 0

section .text
_start:
    mov rdi, 0
    mov rax, SYS_brk
    syscall

    mov rdi, rax
    add rdi, CAPACITY
    mov rax, SYS_brk
    syscall

...
...


Enter fullscreen mode Exit fullscreen mode

Ao analisarmos com gdb:



# Breakpoint na primeira syscall
(gdb) b 18

(gdb) run

# Executa a linha da syscall
(gdb) n

# Em RAX a syscall armazena o endereço do program break, no caso
# 0x403000
(gdb) i r rax
rax            0x403000            4206592

(gdb) x 0x403000
0x403000:       Cannot access memory at address 0x403000


Enter fullscreen mode Exit fullscreen mode

接下来,我们将不再需要访问堆中的新字节。 Vamos 和 com 是 próxima 系统调用:



(gdb) n
(gdb) n

# Antes de executar a syscall, verificamos que o argumento RDI vai 
# conter o endereço desejado para o novo program break, no caso com
# 3 bytes adicionados, 0x403003
(gdb) i r rdi
rdi            0x403003            4206595

# Executa a syscall...
(gdb) n
(gdb) n

# Após a execução da segunda syscall, vemos que em RAX, o program break foi alterado para 0x403003
(gdb) i r rax
rax            0x403003            4206595


Enter fullscreen mode Exit fullscreen mode

集市,可获取记忆中的信息0x4030000x403003



(gdb) x 0x403000
0x403000:       0x00000000
(gdb) x 0x403001
0x403001:       0x00000000
(gdb) x 0x403002
0x403002:       0x00000000
(gdb) x 0x403003
0x403003:       0x00000000


Enter fullscreen mode Exit fullscreen mode

呜! Agora temos no heap uma área reservada especialmente para o nosso querido array, olha que coisa!

可以操作或阵列存储内存吗?

蓬泰罗斯,到处都是蓬泰罗斯

作为一个 Primeira 系统调用,开发者可以渲染代表0x403000Primeiro 程序中断的内存,并在数组中设置以下内容.bss



...
mov rdi, 0
mov rax, SYS_brk
syscall
mov [array], rax      ; <---- breakpoint aqui

mov rdi, rax
add rdi, CAPACITY
mov rax, SYS_brk
syscall
...


Enter fullscreen mode Exit fullscreen mode

Vamos verificar com gdb o 断点 na linha que muda o ponteiro do array:



(gdb) b 19
(gdb) run

(gdb) x &array
0x402004 <array>:       0x00000000

# Executa a linha que muda o ponteiro
(gdb) n

# Agora o ponteiro aponta para o endereço 0x403000, 
# é isto o que queremos
(gdb) x &array
0x402004 <array>:       0x00403000


Enter fullscreen mode Exit fullscreen mode

重要的是数组0x402004在堆中是不存在的,.bss接下来,它的作用代表了记忆的结束,0x403000这是在堆中首次出现的元素。

Agora 提供了一个 3 字节无堆的 proxima 系统调用,程序中断服务修改和操作操作或数组点和连接器的连接。

在第二个系统调用中,您可以操作array自己的勇气,在广场上或在阵列中进行勇气,并从记忆中的元素中获得乐趣。

实际可用程序:



global _start

%define SYS_brk 12
%define SYS_exit 60
%define EXIT_SUCCESS 0
%define CAPACITY 3

section .bss
array: resb 1   ; 0x403000

section .data
pointer: db 0

section .text
_start:
    mov rdi, 0
    mov rax, SYS_brk
    syscall
    mov [array], rax

    mov rdi, rax
    add rdi, CAPACITY
    mov rax, SYS_brk
    syscall

    mov rbx, [array]

    mov r8, 1
    call .append

    mov r8, 2
    call .append

    mov r8, 3
    call .append

    mov r8, 4
    call .append
.exit:
    mov rdi, EXIT_SUCCESS
    mov rax, SYS_exit
    syscall
.append:
    cmp byte [pointer], CAPACITY ; verifica se o array está cheio
    je .done

    mov sil, byte [pointer]
    mov byte [rbx + rsi], r8b
    inc byte [pointer]
.done:
    ret


Enter fullscreen mode Exit fullscreen mode

Explicando cada bloco:



mov rdi, 0
mov rax, SYS_brk
syscall
mov [array], rax


Enter fullscreen mode Exit fullscreen mode
  • Busca o 程序中断 atual e armazena o endereço no ponteiroarray


mov rdi, rax
add rdi, CAPACITY
mov rax, SYS_brk
syscall


Enter fullscreen mode Exit fullscreen mode
  • 修改程序中断,增量 3 字节,初始容量为数组,无堆


; atribuir ao registrador o endereço de memória ao qual o
; ponteiro "array" está apontando
mov rbx, [array] 


Enter fullscreen mode Exit fullscreen mode
  • 设备或 RBX 注册器记忆的渲染。必须注意的是,必须有足够的权限.bss才能获得许可


mov r8, 1
call .append


Enter fullscreen mode Exit fullscreen mode
  • 如果您使用 RDI 来使用系统调用,则可以使用 RDI 注册器来代表元素和辅助功能,但不可以使用 R8 注册器


.append:
    cmp byte [pointer], CAPACITY ; verifica se o array está cheio
    je .done

    mov sil, byte [pointer]
    mov byte [rbx + rsi], r8b    ; indirect-mode addressing
    inc byte [pointer]
.done:
    ret


Enter fullscreen mode Exit fullscreen mode

Agora.append可以对注册器 RBX 的数组操作进行修改,无需堆存储。您可以使用注册器 RAX 来代表 ponteiro pois 系统调用,以恢复程序中断;嵌套 caso trocamos para o RSI(que tem o SIL como suarepresentação de 8-bits menores)。

通过 gdb 执行程序,验证元素的发送方式,无需执行0x403000堆操作,无需注册 RBX 即可使用设备:



# Array aponta para o endereço 0x403000
(gdb) x &array
0x402004 <array>:       0x00403000

# No endereço, temos os elementos adicionados. Yay!
(gdb) x 0x403000
0x403000:       0x00030201

# E o ponteiro de "índice" corretamente representando o fim do array no heap
(gdb) x &pointer
0x402000 <pointer>:     0x00000003


Enter fullscreen mode Exit fullscreen mode

稍后,我们将介绍前组的示例.bss,但不允许使用其他任何元素或组中的任何限制。

Vamos mudar isto,重新调整尺寸并允许新的元素加入爱好者。

调整 com brk

接下来,首先要重新调整尺寸,以限制能力。 Começamos por alterar a rotina .append:



.append:
    cmp byte [pointer], CAPACITY ; verifica se o array está cheio
    je .resize

    mov sil, byte [pointer]
    mov byte [rbx + rsi], r8b
    inc byte [pointer]
.done:
    ret
.resize:
    ...


Enter fullscreen mode Exit fullscreen mode

在所有的.doneestiver cheio 中进行 fazer 跳跃,在 sub-rotina chamada 外跳跃.resize,然后将 syscall 放入 novamente,修改 assim 或程序中断uma nova are na memória,首先执行数组的操作:



.append:
    cmp byte [pointer], CAPACITY ; verifica se o array está cheio
    je .resize

    mov sil, byte [pointer]
    mov byte [rbx + rsi], r8b
    inc byte [pointer]
.done:
    ret
.resize:
    mov rdi, 0
    mov rax, SYS_brk
    syscall

    mov rdi, rax            ; RDI passa a representar o break atual
    add rdi, CAPACITY       ; adiciona 3 bytes, ficando 0x403006
    mov rax, SYS_brk
    syscall
    jmp .append


Enter fullscreen mode Exit fullscreen mode
  • 调整大小或中断实际大小的初始系统调用,不能进行任何更改0x403003,不能启动数组程序
  • 调整大小修改或中断的第二个系统调用,alocando assim mais 3 字节无堆
  • 调整大小、返回功能、启动并.append执行必要的逻辑或无数组元素

下一步,新的操作按钮将存储在无阵列的附加信息中,并修改为可用的名称。

Se executarmos o programa exatamente assim, vamos enfrentar um Problema, pois:

  • a cada vez que éfeito or resize, salta para o início da rotina
  • 验证或阵列 (pointeiro) 为初始容量,但不包括 3. 为 valor 3 提供支持,进入新版本后无需调整角色大小,无限循环可无限调整记忆大小

解析器是,precisamos comparar o 指针com a capacidade atual(modificada),e portanto vamos adicionar um valor na seção .dataquerepresenta a capacidade atual:



%define CAPACITY 3

section .data
pointer: db 0
currentCapacity: db CAPACITY ; começa com 3


Enter fullscreen mode Exit fullscreen mode

如果.append您需要进行比较、调整大小、进行修改、永久修复程序或程序的初始值,则可以进行调整。currentCapacityCAPACITY



.append:
    mov r9, [currentCapacity]
    cmp byte [pointer], r9b     ; verifica se o array está cheio
    je .resize
...


Enter fullscreen mode Exit fullscreen mode

E, após or redimensionamento antes de voltar pro .append, vamos Incrementar or valor da capacidade inicial à capacidade atual:



.resize:
    mov rdi, 0
    mov rax, SYS_brk
    syscall

    mov rdi, rax
    add rdi, CAPACITY
    mov rax, SYS_brk
    syscall

    mov r10, currentCapacity
    add byte [r10], CAPACITY
    jmp .append


Enter fullscreen mode Exit fullscreen mode

如果执行程序,则可以在 4 个元素中成功执行,无需重新调整尺寸:



(gdb) x 0x403000
0x403000:       0x04030201


Enter fullscreen mode Exit fullscreen mode

是否有一些额外的建议或元素?



...
    mov r8, 4
    call .append

    mov r8, 5
    call .append

    mov r8, 6
    call .append

    mov r8, 7
    call .append
...


Enter fullscreen mode Exit fullscreen mode


# Podemos ver que o currentCapacity é 9, ou seja, foram feitos 
# 2 redimensionamentos. Nosso array consegue agora acomodar até 9 elementos, 
# pelo que ao adicionar o décimo elemento, mais um resize seria feito.
(gdb) x &currentCapacity
0x402001 <currentCapacity>:     0x09

# Buscando os 9 primeiros hexabytes no endereço do array no heap
(gdb) x/9xb  0x403000
0x403000:       0x01    0x02    0x03    0x04    0x05    0x06    0x07    0x00
0x403008:       0x00


Enter fullscreen mode Exit fullscreen mode

这也太酷了吧?


最终程序

最后一个程序是,使用 3 个元素的初始数组来重新调整系统调用的大小brk,并与数组元素保持一致:



global _start

%define SYS_brk 12
%define SYS_exit 60
%define EXIT_SUCCESS 0
%define CAPACITY 3

section .bss
array: resb 1

section .data
pointer: db 0
currentCapacity: db CAPACITY ; capacidade inicial é 3

section .text
_start:
    mov rdi, 0
    mov rax, SYS_brk
    syscall
    mov [array], rax

    mov rdi, rax
    add rdi, CAPACITY
    mov rax, SYS_brk
    syscall

    mov rbx, [array]

    mov r8, 1
    call .append

    mov r8, 2
    call .append

    mov r8, 3
    call .append

    mov r8, 4
    call .append

    mov r8, 5
    call .append

    mov r8, 6
    call .append

    mov r8, 7
    call .append
.exit:
    mov rdi, EXIT_SUCCESS
    mov rax, SYS_exit
    syscall
.append:
    mov r9, [currentCapacity]
    cmp byte [pointer], r9b ; verifica se o array está cheio
    je .resize

    mov sil, byte [pointer]
    mov byte [rbx + rsi], r8b
    inc byte [pointer]
.done:
    ret
.resize:
    mov rdi, 0
    mov rax, SYS_brk
    syscall

    mov rdi, rax
    add rdi, CAPACITY
    mov rax, SYS_brk
    syscall

    mov r10, currentCapacity
    add byte [r10], CAPACITY
    jmp .append


Enter fullscreen mode Exit fullscreen mode

结论

下一步,您将在 Assembly x86 中实现阵列,并了解重要的内存布局、注册操作和内存分配brk

作为未来的基础,您可以假装使用文件和后面的列表来实现连接。

敬请关注!


参考资料


寻址模式
https://www.tutorialspoint.com/assembly_programming/assembly_addressing_modes.htm
系统调用 brk
https://man7.org/linux/man-pages/man2/brk.2.html
ASCII 字符表
https://www.asciicharstable.com/_site_media/ascii/ascii-chars-table-landscape.jpg

文章来源:https://dev.to/leandronsp/arrays-em- assembly-x86-55hb