如何用汇编语言(ASM)检查“数组的长度”,

问题描述 投票:0回答:9

我刚刚开始学习汇编语言。在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 来查找元素的总数。

assembly
9个回答
13
投票

回答这个问题的最佳方法是使用 C 示例。在 C 中,有两种方法可以跟踪数组的长度:

  1. 您存储一个变量,告诉您创建数组的时间。
  2. 您可以执行字符串所做的操作,并将最后一个元素设置为 0。然后,您可以实现一个“字符串”长度函数,该函数循环遍历数组,直到找到零。

对于第一个示例,根据您使用的汇编器,您可能可以使用一些技巧。例如,在 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

请注意,我还没有测试过。只是为了给你一个想法。

编辑我在Linux上测试了

x86_64
版本,使用
rdi
作为param1,传入
int arr[10] = {1,2,3,4,5,6,7,8,9,0};
。按预期返回
9
。请注意,在 Linux 上,
mystrlen
前面的下划线是不必要的。


6
投票

汇编比 Java 低级得多。除此之外,这意味着不存在“数组”这样的东西。至少以您所知道的安全 Java 形式。

相当于数组的是分配一块内存,并将其视为数组。不过,长度等您必须自行管理,因为您拥有的只是一块包含数据的内存。如果您想存储任何元数据,例如长度,您必须自己执行此操作。

Java 中的数组包含长度等元数据,并进行边界检查。它们所做的事情与您必须做的事情相同,只是它们隐藏了它,因此您不必担心这些事情。

我建议您看一下以下内容,了解如何在汇编中创建和使用相当于数组的内容:


2
投票

汇编中不存在数组这样的东西(据我所知)。如果您愿意,您可以自由地发明数组的工作原理。

如果您正在阅读编译器生成的程序集,那么您将必须专门询问该编译器。

实现此目的的一种方法是允许数组的第一个字节存储每个元素的长度。另一种方法是以 null 终止数组(这通常是维护字符串的方式)。


2
投票

您可以使用以下程序(

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
投票

我发现这个线程对这个主题非常有启发:Asm示例:查找具有不同数据类型的数组的大小


1
投票
a db 10h,20h,30h,40h,50h,60h
n db n-a

在上面的代码中,'a'是一个默认有6个元素的数组,'a'将指向数组的第一个元素,'n'将在数组之后初始化。所以值'n-a'将对应于我们存储在n中的数组的长度。 不要初始化 a 和 n 之间的其他变量。这可能会给您带来错误的结果。


0
投票

MOV EAX,长度数据

返回数组变量中的项目数。


0
投票

我想这会对你有帮助......

.数据

num db 2,4,6,8,10

.代码

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

输出=5


0
投票

https://cpuulator.01xz.net/?sys=arm-de1soc&d_audio=48000

.global _start
_start:
.data
    arr:
        .byte 83, 12, 35, 23, 47, 33, 50, 91, 101, 55, 63, 85, 78
        .equ len, .-arr
    
© www.soinside.com 2019 - 2024. All rights reserved.