如何处理非固定尺寸阵列?

发布于 2025-02-12 05:45:58 字数 5767 浏览 1 评论 0原文

今天,我正在研究阵列和寻址模式,因此我制作了这个片段来训练自己。一切都很好(显然),但是我选择了使用固定尺寸阵列的最简单方法。我的问题是关于动态内存分配。在我的代码中,我的数组数组array2具有固定的大小(8 * 4(int))。如果我想扩展它们或与C概念交谈,请制作realloc或类似的内容,取决于大小的实时值,我是否必须实现诸如sys_brk 和mmap我自己在汇编中 还是还有其他选择?另一个问题涉及我的代码部分用于逆转数组(标签。reverversing),我知道它们比我的解决方案更快,因此,如果您能给我一些建议,那就很好。

%define ARRAY_LEN   8

%macro print 2
    mov     eax, 4
    mov     ebx, 1
    mov     ecx, %1
    mov     edx, %2
    int     0x80
%endmacro

%macro exit 0
    xor     ebx, ebx 
    mov     eax, 1
    int     0x80
%endmacro

section .bss
    sumarrays       resd    1
    dynarray        resd    256

section .rodata
    highest     equ     0x78
    evensum     equ     0x102
    sumarray1   equ     0x1e6
    sumarray2   equ     0x256

section .data
    revarray    times ARRAY_LEN dd 0
    strok       db      "Good result !", 0xa, 0
    lenstrok    equ     $ - strok
    strerror    db      "Bad result !", 0xa, 0
    lenerror    equ     $ - strerror
    array       dd      0x33, 0x21, 0x32, 0x78, 0x48, 0x77, 0x19, 0x10
    array2      dd      0x12, 0x98, 0x65, 0x62, 0x4e, 0x3e, 0x1f, 0x3a

section .text
    global sort
    global sum

    global _start

_start:

    ; sort array from highest value to lowest value

    sub     esp, 8
    push    ARRAY_LEN
    push    array
    call    sort
    add     esp, 8
    and     esp, 0xfffffff0

    ; copying array into some another ones : array -> revarray

    mov     esi, eax
    mov     edi, revarray
    mov     ecx, ARRAY_LEN
    rep     movsd

    ; now let's reverse the array

    mov     esi, revarray          ;esi = address of array                    
    mov     ecx, ARRAY_LEN          ;ecx = number of elements
    lea     edi, [esi + ecx * 4 - 4]

.reversing:
    mov     eax, [esi]              ;eax = value at start
    mov     ebx, [edi]              ;ebx = value at end
    mov     [edi], eax
    mov     [esi], ebx
    add     esi, 4                  ;incrementing address of next item at start
    sub     edi, 4                  ;incrementing address of next item at end
    cmp     esi, edi                ;middle reached ?
    jb      .reversing              ;no we continue

.reversed:

    ;after, we compute the sum of the elements in the array

    mov     esi, revarray       ; address of array
    mov     edx, ARRAY_LEN      ; num elem of array
    sub     esp, 8
    call    arraysum            ; sum computation
    add     esp, 8
    cmp     eax, sumarray1      ; we check the result to be sure
    jne     .failure

    ; merging array2 with array
    ; esi = source address of first array
    ; edi = address of second array, the destination one
    mov     esi, array2
    mov     edi, array
    sub     esp, 8
    call    mergearrays
    add     esp, 8

    ; we compute the sum of the merged arrays into the new (old one in fact)
    mov     esi, array
    mov     ecx, ARRAY_LEN
    add     esp, 8
    call    arraysum
    add     esp, 8

    cmp     eax, 0x43c      ; we check the result to be sure
    jne     .failure        ; if not egal, exit

    ; compute the sum of even numbers only in the array
    ; set up edx to 0 at beginning of loop
    ; cmova edx, $value_even_number
    mov     esi, revarray
    xor     ebx, ebx
    xor     ecx, ecx

.iterate: 
    xor     edx, edx                ; setting up edx to 0
    mov     eax, [esi + ecx * 4]
    test    al, 1                   ; CF == 0 ? so it's an even number
    cmovz   edx, eax                ; we store the value of current element in edx
    add     ebx, edx                ; so in case of odd number => add 0
    inc     ecx
    cmp     ecx, ARRAY_LEN          ; end of array reached ?
    jne     .iterate                ; no, we continue
    cmp     ebx, 0x102              ; check if result is good
    je      .success
    jmp     .failure
    exit     

.success:
    print   strok, lenstrok
    exit

.failure:
    print   strerror, lenerror
    exit

; ********************************************
; computes the sum of all elements of an array
; esi = address of the array
; edx = number of elements in array
; output : eax
; ********************************************
arraysum:
    push    ebx
    xor     ebx, ebx
    xor     ecx, ecx

.arraysum:
    mov     eax, [esi + ecx *4]
    add     ebx, eax
    inc     ecx
    cmp     ecx, edx
    je      .sumdone
    jmp     .arraysum

.sumdone:
    mov     eax, ebx
    pop     ebx
    ret
    
; *********************************************
; procedure that sort array from highest to lowest value
; first arg = address of the array
; second arg = number of elements in a array
; return : eax, sorted array
; ********************************************
sort:
    push    ebp
    mov     ebp, esp
    mov     edx, [ebp + 12]

.loop1:
    mov     esi, [ebp + 8]
    mov     ecx, [ebp + 12]

.loop2:
    mov     eax, [esi]
    mov     ebx, [esi + 4]
    cmp     eax, ebx
    jg      .skip

    mov     [esi], ebx
    mov     [esi + 4], eax

.skip:
    add     esi, 4          ;perform loop checks
    dec     ecx
    cmp     ecx, 1
    ja      .loop2
    dec     edx
    ja      .loop1

    mov     eax,[ebp + 8]   ; save result in eax

    mov     esp,ebp
    pop     ebp
    ret

; ****************************************************
; function adding two arrays merging them
; esi = address of first array
; edi = address of second array (destination array)
; ****************************************************
mergearrays:
    xor     ecx, ecx

.merging:
    mov     eax, [esi + ecx * 4]
    xadd    [edi + ecx * 4], eax
    inc     ecx
    cmp     ecx, ARRAY_LEN
    je      .mergedone
    jmp     .merging

.mergedone:
    ret

Today I'm working on arrays and addressing modes so I made this snippet to train myself. Everything is working fine (apparently) but I chose the easiest way using fixed size arrays. My question is about dynamic memory allocation. In my code, my arrays arrayand array2 have a fixed size (8 * 4(int)). If I wanted to extend them, or to speak with C concepts, make a realloc or something like depending on real time values for the size, may I have to implement system calls like sys_brk and mmapby myself in assembly
or is there an other option ? The other question deals with the part of my code used to reverse an array (label .reversing) I know they are faster solutions than mine so if you could give me some advices, it would be nice.

%define ARRAY_LEN   8

%macro print 2
    mov     eax, 4
    mov     ebx, 1
    mov     ecx, %1
    mov     edx, %2
    int     0x80
%endmacro

%macro exit 0
    xor     ebx, ebx 
    mov     eax, 1
    int     0x80
%endmacro

section .bss
    sumarrays       resd    1
    dynarray        resd    256

section .rodata
    highest     equ     0x78
    evensum     equ     0x102
    sumarray1   equ     0x1e6
    sumarray2   equ     0x256

section .data
    revarray    times ARRAY_LEN dd 0
    strok       db      "Good result !", 0xa, 0
    lenstrok    equ     $ - strok
    strerror    db      "Bad result !", 0xa, 0
    lenerror    equ     $ - strerror
    array       dd      0x33, 0x21, 0x32, 0x78, 0x48, 0x77, 0x19, 0x10
    array2      dd      0x12, 0x98, 0x65, 0x62, 0x4e, 0x3e, 0x1f, 0x3a

section .text
    global sort
    global sum

    global _start

_start:

    ; sort array from highest value to lowest value

    sub     esp, 8
    push    ARRAY_LEN
    push    array
    call    sort
    add     esp, 8
    and     esp, 0xfffffff0

    ; copying array into some another ones : array -> revarray

    mov     esi, eax
    mov     edi, revarray
    mov     ecx, ARRAY_LEN
    rep     movsd

    ; now let's reverse the array

    mov     esi, revarray          ;esi = address of array                    
    mov     ecx, ARRAY_LEN          ;ecx = number of elements
    lea     edi, [esi + ecx * 4 - 4]

.reversing:
    mov     eax, [esi]              ;eax = value at start
    mov     ebx, [edi]              ;ebx = value at end
    mov     [edi], eax
    mov     [esi], ebx
    add     esi, 4                  ;incrementing address of next item at start
    sub     edi, 4                  ;incrementing address of next item at end
    cmp     esi, edi                ;middle reached ?
    jb      .reversing              ;no we continue

.reversed:

    ;after, we compute the sum of the elements in the array

    mov     esi, revarray       ; address of array
    mov     edx, ARRAY_LEN      ; num elem of array
    sub     esp, 8
    call    arraysum            ; sum computation
    add     esp, 8
    cmp     eax, sumarray1      ; we check the result to be sure
    jne     .failure

    ; merging array2 with array
    ; esi = source address of first array
    ; edi = address of second array, the destination one
    mov     esi, array2
    mov     edi, array
    sub     esp, 8
    call    mergearrays
    add     esp, 8

    ; we compute the sum of the merged arrays into the new (old one in fact)
    mov     esi, array
    mov     ecx, ARRAY_LEN
    add     esp, 8
    call    arraysum
    add     esp, 8

    cmp     eax, 0x43c      ; we check the result to be sure
    jne     .failure        ; if not egal, exit

    ; compute the sum of even numbers only in the array
    ; set up edx to 0 at beginning of loop
    ; cmova edx, $value_even_number
    mov     esi, revarray
    xor     ebx, ebx
    xor     ecx, ecx

.iterate: 
    xor     edx, edx                ; setting up edx to 0
    mov     eax, [esi + ecx * 4]
    test    al, 1                   ; CF == 0 ? so it's an even number
    cmovz   edx, eax                ; we store the value of current element in edx
    add     ebx, edx                ; so in case of odd number => add 0
    inc     ecx
    cmp     ecx, ARRAY_LEN          ; end of array reached ?
    jne     .iterate                ; no, we continue
    cmp     ebx, 0x102              ; check if result is good
    je      .success
    jmp     .failure
    exit     

.success:
    print   strok, lenstrok
    exit

.failure:
    print   strerror, lenerror
    exit

; ********************************************
; computes the sum of all elements of an array
; esi = address of the array
; edx = number of elements in array
; output : eax
; ********************************************
arraysum:
    push    ebx
    xor     ebx, ebx
    xor     ecx, ecx

.arraysum:
    mov     eax, [esi + ecx *4]
    add     ebx, eax
    inc     ecx
    cmp     ecx, edx
    je      .sumdone
    jmp     .arraysum

.sumdone:
    mov     eax, ebx
    pop     ebx
    ret
    
; *********************************************
; procedure that sort array from highest to lowest value
; first arg = address of the array
; second arg = number of elements in a array
; return : eax, sorted array
; ********************************************
sort:
    push    ebp
    mov     ebp, esp
    mov     edx, [ebp + 12]

.loop1:
    mov     esi, [ebp + 8]
    mov     ecx, [ebp + 12]

.loop2:
    mov     eax, [esi]
    mov     ebx, [esi + 4]
    cmp     eax, ebx
    jg      .skip

    mov     [esi], ebx
    mov     [esi + 4], eax

.skip:
    add     esi, 4          ;perform loop checks
    dec     ecx
    cmp     ecx, 1
    ja      .loop2
    dec     edx
    ja      .loop1

    mov     eax,[ebp + 8]   ; save result in eax

    mov     esp,ebp
    pop     ebp
    ret

; ****************************************************
; function adding two arrays merging them
; esi = address of first array
; edi = address of second array (destination array)
; ****************************************************
mergearrays:
    xor     ecx, ecx

.merging:
    mov     eax, [esi + ecx * 4]
    xadd    [edi + ecx * 4], eax
    inc     ecx
    cmp     ecx, ARRAY_LEN
    je      .mergedone
    jmp     .merging

.mergedone:
    ret

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文