Assembly 汇编语言中的数组

Assembly 汇编语言中的数组,assembly,x86,nasm,Assembly,X86,Nasm,如果我必须把short int v[5]={1,2,3,4,5}翻译成assemblycode,我该怎么做?如果我在做这样的事情,这没关系: Enter 16,0 Mov ebp-4, 1 Mov ebp-8, 2 Mov ebp-12, 3 Mov ebp-16, 4 谢谢。您可以这样做,但正如@Ped7g所指出的,您需要限定符。v[0]在内存中要少20个字节,因此您必须以相反的顺序写入它们 enter 20, 0 ; At this point ESP is the

如果我必须把
short int v[5]={1,2,3,4,5}
翻译成
assembly
code,我该怎么做?如果我在做这样的事情,这没关系:

Enter 16,0
Mov ebp-4, 1
Mov ebp-8, 2
Mov ebp-12, 3
Mov ebp-16, 4

谢谢。

您可以这样做,但正如@Ped7g所指出的,您需要限定符。v[0]在内存中要少20个字节,因此您必须以相反的顺序写入它们

        enter   20, 0

; At this point ESP is the pointer to v[]

        mov     dword [bp-20], 1
        mov     dword [bp-16], 2
        mov     dword [bp-12], 3
        mov     dword [bp-8], 4
        mov     dword [bp-4], 5
你必须使用德沃德的原因是因为想象一下堆栈的竞争,如下所示

2F 3D 17 0A 41 FF 16 18 03 22 19 0D 01 F3 D1 0C 12 02 EE 4A

对字节[bp-4]使用字节限定符,5将只更改2F。但是,DWORD会更改所有4个字节,然后变为

05 00 00

为了节省程序空间,您还可以

        push    bp
        mov     bp, sp
        push    5
        push    4
        push    3
        push    2
        push    1
对此有一些注意事项,但由于IA32是结构化的,因此将扩展到32位。但使用的代码要少得多

在程序外声明,则它将成为

    v:    dw    1, 2, 3, 4, 5

你可以这样做,但正如@Ped7g所指出的,你需要限定符。v[0]在内存中要少20个字节,因此您必须以相反的顺序写入它们

        enter   20, 0

; At this point ESP is the pointer to v[]

        mov     dword [bp-20], 1
        mov     dword [bp-16], 2
        mov     dword [bp-12], 3
        mov     dword [bp-8], 4
        mov     dword [bp-4], 5
你必须使用德沃德的原因是因为想象一下堆栈的竞争,如下所示

2F 3D 17 0A 41 FF 16 18 03 22 19 0D 01 F3 D1 0C 12 02 EE 4A

对字节[bp-4]使用字节限定符,5将只更改2F。但是,DWORD会更改所有4个字节,然后变为

05 00 00

为了节省程序空间,您还可以

        push    bp
        mov     bp, sp
        push    5
        push    4
        push    3
        push    2
        push    1
对此有一些注意事项,但由于IA32是结构化的,因此将扩展到32位。但使用的代码要少得多

在程序外声明,则它将成为

    v:    dw    1, 2, 3, 4, 5

这是什么汇编程序语法?英特尔语法要求在内存引用周围使用
[]
(从操作数顺序看,它类似于英特尔语法)。每个汇编程序都有细微的差别,MASM:
mov-word-ptr[ebp-4],1
,NASM:
mov-word[ebp-4],1
。。。您可以将值相隔2个字节,因为
short int
int16\u t
(可能)。此外,如果您在内存中读取这些值,您将以@ebp-16地址结束:4,3,2,1。。。碳源为1,2,3,4,5。。。所以你很接近,但不一样,你有正确的原则,现在调整细节。试试看戈德博尔特:嘿,谢谢你。我想为NASM;)那么“v dw 1,2,3,4,5”呢?@Tommylee2k不能用于存储在堆栈中的局部变量,只能用于
.data
中的全局/静态变量。Andreea:将“-fno omit frame pointer”添加到上一个链接中的gcc选项将强制其使用
ebp
符号,更接近原始源代码:(如果您没有经验发现如何在第一个变量中利用
esp
,那么您应该更容易理解这个变量->但我强烈建议将所有变量(包括-O3变量)复制到调试器中,并对它们进行一步推理,了解它们的差异以及每个变量的工作方式=将教会您很多)他没有说他想要的是数据的局部变量;-)tbh他没有指定任何东西。我们只是从他的代码片段中推断出这是什么汇编程序语法?英特尔语法要求在内存引用周围使用
[]
(从操作数顺序看,它类似于英特尔语法)。每个汇编程序都有细微的差别,MASM:
mov-word-ptr[ebp-4],1
,NASM:
mov-word[ebp-4],1
。。。您可以将值相隔2个字节,因为
short int
int16\u t
(可能)。此外,如果您在内存中读取这些值,您将以@ebp-16地址结束:4,3,2,1。。。碳源为1,2,3,4,5。。。所以你很接近,但不一样,你有正确的原则,现在调整细节。试试看戈德博尔特:嘿,谢谢你。我想为NASM;)那么“v dw 1,2,3,4,5”呢?@Tommylee2k不能用于存储在堆栈中的局部变量,只能用于
.data
中的全局/静态变量。Andreea:将“-fno omit frame pointer”添加到上一个链接中的gcc选项将强制其使用
ebp
符号,更接近原始源代码:(如果您没有经验发现如何在第一个变量中利用
esp
,那么您应该更容易理解这个变量->但我强烈建议将所有变量(包括-O3变量)复制到调试器中,并对它们进行一步推理,了解它们的差异以及每个变量的工作方式=将教会您很多)他没有说他想要的是数据的局部变量;-)tbh他没有指定任何东西。我们只是从他的代码片段中推断出这一点,您正在堆栈上定义
v:dd1,2,3,4,5
。可以在堆栈内存中定义短数组,即使默认的
push/pop
使用DWORD,您甚至可以使用
push
,例如
push 0x50004
push 0x30002
push 0x10000
将单词数组设置为原始
esp-10
,并在esp-11和esp-12上使用2B垃圾(或者新的esp+0、esp+1和数组位于esp+2到esp+11之间)。如果您查看我的评论中的godbolt链接,C编译器确实会在堆栈中生成短数组(但通过使用
mov
,而不是
push
)。您正在堆栈上定义
v:dd 1、2、3、4、5
。可以在堆栈内存中定义短数组,即使默认的
push/pop
使用DWORD操作,您甚至可以使用
push
,如
push 0x50004
push 0x30002push 0x10000在原始
esp中使用字数组-10
在esp-11和esp-12上有2B垃圾(或新的esp+0、esp+1,数组在esp+2到esp+11)。如果您想查看我的评论中的锁紧螺栓链接,C编译器确实会在堆栈中生成短数组(但通过使用
mov
,而不是
push
)。