Как проверить «длину массива» на ассемблере (ASM), - PullRequest
6 голосов
/ 31 января 2011

Я только начал изучать ассемблер.В Java, если у нас есть массив, мы всегда можем использовать array.length, чтобы получить его длину.Есть ли такая вещь в сборке?Если да, может кто-нибудь подсказать мне, пожалуйста?

Редактировать:

Мои извинения, я знаю, что в сборке нет массивов, я пытался упростить вещи.

Что я имел в виду, если, например, у меня есть переменная

data DB 1,2,3,5,7,8,9,10

Учитывая, что БД может содержать любое количество элементов, как я могу проверить общую переменную, которую она содержит?

Что-то вроде java, где используется массив int для хранения

int data = {1,2,3,4,57,8,9,10};

Мы можем просто data.length найти общее количество элементов.

Ответы [ 8 ]

12 голосов
/ 31 января 2011

Лучший способ ответить на этот вопрос - использовать примеры на языке C.В C есть два способа отслеживать длину массива:

  1. Вы храните переменную, сообщающую вам, как долго вы создали массив.
  2. Вы делаете то, что делают строкии последний элемент равен 0. Затем вы можете реализовать функцию длины «string», которая перебирает массив, пока не найдет ноль.

Для первого примера, в зависимости от того, каким ассемблером вы являетесьиспользуя, вы можете использовать некоторые приемы.Например, в nasm вы можете сделать это:

SECTION .data       

msg:    db "Hello World",10,0  ; the 0-terminated string.
len:    equ $-msg              ; "$" means current address.

Как видите, мы используем оператор equ, чтобы получить nasm для вычисления разницы между текущим адресом и началом msg, чтодолжен равняться его длине.В качестве альтернативы вы можете просто написать длину в виде цифры.

Во втором случае вы можете легко написать небольшую функцию для этого.Грубо говоря, если вы:

SECTION .text

global _mystrlen

_mystrlen:

    push    ebp        ; conform to C calling conventions.
    mov     ebp, esp

    xor     eax, eax
    lea     ecx, [esp+8]   ; load the start of the array into ecx
    jecxz   end            ; jump if [ecx] is zero.

loop:
    add     eax, 1     ; could use inc eax as well. 
    add     ecx, 4     ; always increment by (sizeof(int)). Change as appropriate
    mov     edx, [ecx] ; load ecx
    cmp     edx, 0     ; compare with zerp
    je      end        ; if ecx is zero, we're done.
    jmp     loop       ; if ecx isn't zero, loop until it is.

end:
    leave              ; restore stack frame
    ret                ; return. eax is retval

Обратите внимание, что я не проверял это.Это просто для того, чтобы дать вам представление.

Edit Я протестировал x86_64 версию для Linux, используя rdi в качестве param1, передавая int arr[10] = {1,2,3,4,5,6,7,8,9,0};.Возвращает 9 как ожидалось.Обратите внимание, что в Linux подчеркивание, предшествующее mystrlen, не требуется.

7 голосов
/ 31 января 2011

Сборка намного ниже, чем Java. Это, помимо прочего, означает, что нет такой вещи, как «массив». По крайней мере, в безопасной форме Java, в которой вы это знаете.

То, что было бы эквивалентно массиву, - это выделение фрагмента памяти и обработка его как массива. Длина и тому подобное, вам придется управлять самостоятельно, так как все, что у вас есть, это кусок памяти, содержащий ваши данные. Если вы хотите сохранить какие-либо метаданные, например, длину, вам придется сделать это самостоятельно.

Массивы, как вы их знаете в Java, содержат метаданные, такие как длина, и выполняют проверку границ. Они делают то же самое, что и вам, только они скрывают это, так что вам не придется беспокоиться об этих вещах.

Я предлагаю вам взглянуть на следующие сведения о том, как обычно создавать и использовать то, что эквивалентно массиву в сборке:

2 голосов
/ 31 января 2011

В сборке нет такого понятия, как массив (насколько я знаю). Вы можете придумать, как работает массив, если хотите.

Если вы читаете сборку, сгенерированную компилятором, вам придется спросить об этом компиляторе.

Один из способов сделать это - разрешить первому байту массива хранить длину каждого элемента. Другим способом было бы завершить массив нулем (обычно это так, как поддерживаются строки).

1 голос
/ 18 октября 2018

Вы можете использовать следующую программу (ATT синтаксис сборки) для определения количества элементов в массиве:

.section .data
array:
    .long 3,5,8             # create an array of 32-bit integers
    arrsize = . - array     # in bytes (assemble-time constant, not stored)
    arrlen = (. - array)/4  # in dwords

.section .text
.globl _start
_start:

    mov   $arrlen, %edi
    mov   $60, %eax      # __NR_exit  in asm/unistd_64.h
    syscall              # sys_exit(arrlen)

Собрать и связать программу:

gcc -c array.s && ld array.o
  #or
gcc -nostdlib -static array.s

Результат 3, как и ожидалось:

>./a.out            # run program in shell
>echo $?            # check the exit status (which is the number of elements in the array)
3
1 голос
/ 31 января 2011
0 голосов
/ 25 марта 2018
a db 10h,20h,30h,40h,50h,60h
n db n-a

в вышеприведенном коде «a» - это массив, содержащий 6 элементов по умолчанию. «A» будет указывать на первый элемент массива, а «n» будет инициализироваться сразу после массива. поэтому значение 'n-a' будет соответствовать длине массива, который мы храним в n. не инициализируйте другие переменные между a и n. Это может дать вам неправильные результаты.

0 голосов
/ 01 февраля 2015

Я думаю, что это поможет вам ....

.data

num db 2,4,6,8,10

.code

main proc
mov eax,0 ; initialize with zero
mov ax,lengthof num 

output = 5

0 голосов
/ 27 октября 2013

MOV EAX, LENGTHOF data

Возвращает количество элементов в переменной массива.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...