Assembly 使用从外部操作码获得的数据
为了流利地使用漂亮的汇编语言,我想不出比充分理解我在一开始遇到的问题的细节更好的方法,杰夫·邓特曼(Jeff Duntemann)的《汇编语言一步一步》(Assembly Language Step by Step)这本初学者书中很可能没有解释: 我有一个文件hexlib.asm,它使用以下命令组装并生成其hexlib和hexlib.o对应项:Assembly 使用从外部操作码获得的数据,assembly,global,extern,Assembly,Global,Extern,为了流利地使用漂亮的汇编语言,我想不出比充分理解我在一开始遇到的问题的细节更好的方法,杰夫·邓特曼(Jeff Duntemann)的《汇编语言一步一步》(Assembly Language Step by Step)这本初学者书中很可能没有解释: 我有一个文件hexlib.asm,它使用以下命令组装并生成其hexlib和hexlib.o对应项: nasm -f elf -g -F stabs hexlib.asm ld -o hexlib hexlib.o -melf_i386 nasm
nasm -f elf -g -F stabs hexlib.asm
ld -o hexlib hexlib.o -melf_i386
nasm -f elf -g -F stabs main.asm
ld -o main main.o libraries/hexlib/hexlib.o -melf_i386
asm文件包含以下基本代码:
GLOBAL TestString
SECTION .data
TestString db 'Gewurztraminer'
SECTION .bss
SECTION .text
;_start is omitted because the main.asm file already uses it.
;I got a warning from NASM, but, like any novice, I ignored it
;because I have enough on my mind already.
我还有main.asm,它使用以下命令:
nasm -f elf -g -F stabs hexlib.asm
ld -o hexlib hexlib.o -melf_i386
nasm -f elf -g -F stabs main.asm
ld -o main main.o libraries/hexlib/hexlib.o -melf_i386
main.asm文件中的代码如下:
(我正在寻求为我的公司制造一台机器,我希望出售,所以请原谅德瑞克保留的所有权利
;#################################################################
;#################################################################
;## ##
;## ************************************ ##
;## * AUTHOR: cvgbhfghfhf * ##
;## * ALL RIGHTS RESERVED * ##
;## ************************************ ##
;## _________________________________________________________ ##
;## | |_REGISTER_|_________CONTAINS_________| ##
;## | | | | ##
;## | INPUT REGISTERS | | | ##
;## | | | | ##
;## |___________________|__________|__________________________| ##
;## _________________________________________________________ ##
;## | |_REGISTER_|_________CONTAINS_________| ##
;## | | | | ##
;## | OUTPUT REGISTERS | | | ##
;## | | | | ##
;## |___________________|__________|__________________________| ##
;## ##
;## _________________________________________________________ ##
;## | | | ##
;## | DESCRIPTION | | ##
;## | OF FUNCTION | | ##
;## |___________________|_____________________________________| ##
;## | | | ##
;## | PROCEDURES | | ##
;## |___________________|_____________________________________| ##
;## ##
;#################################################################
;#################################################################
;########## Build using these commands ##########
;nasm -f elf -g -F stabs main.asm
;ld -o main main.o libraries/declib/declib.o -melf_i386
;################################################
EXTERN TestString
SECTION .data ; Section containing initialised data. <=============
TestStringLen equ $-TestString
SECTION .bss ; Section containing uninitialized data. <===========
SECTION .text ; Section containing the code of procedures. <=======
Display:
mov eax, 4
mov ebx, 1
mov ecx, TestString
mov edx, TestStringLen
int 80h
Done: mov eax, 1
mov ebx, 0
int 80h
global _start ; Linker needs this to find the entry point. <=======
_start:
nop ; GDB requirement. <=================================
call Display
call Done
;+~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*+
;* INPUT REGISTERS: *
;~ ~
;* OUTPUT REGISTERS: *
;~ ~
;* DESCRIPTION: *
;~ ~
;+~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*+
第46行是:
TestStringLen equ $-TestString
我的问题是:到底发生了什么?很明显,TestString并不是我在hexlib.asm中初始化的TestString的精确副本。这与段寄存器有关吗?如果涉及段寄存器,请仔细了解到底发生了什么
到底发生了什么事
代码中有两个问题:
第一个问题是不支持给定的重新定位类型。这意味着什么
让我们看看下面的代码:
test1 equ 10
mov eax, test1+20
extern test1
mov eax, test1+20
汇编程序将从汇编程序文件创建一个目标文件(.o或.obj)。在目标文件中存储以下代码:
mov eax, 30
mov eax, 20
现在让我们看一下以下代码:
test1 equ 10
mov eax, test1+20
extern test1
mov eax, test1+20
在目标文件中存储以下代码:
mov eax, 30
mov eax, 20
此外,还存储了一个“重定位”(一个被“ld”理解的特殊数据项),它告诉链接器(“ld”),一旦知道该地址,“test1”的地址(或值)就必须添加到数字20中
根据使用的文件格式,支持某些操作(如将地址添加到值),而不支持其他操作。我知道的任何文件格式都不支持从值中减去地址,如$-TestString
因此,“nasm”不可能为指令mov-edx,TestStringLen
:在.o或.obj文件中,这将导致指令mov-edx,0
和信息“ld”必须从值0中减去TestString
的地址。但是,文件格式不支持“从…”中减去地址”类型的条目
第二个问题是您不知道“ld”将把第二个数据段放在哪里
请记住以下代码
SomeText db "Test"
SomeOtherItem db "Hello"
AThirdItem db "World!"
SomeTextLength equ $-SomeText
…将不会导致SomeTextLength
的值为4,而是导致值为15。这是因为$-SomeText
表示:从SomeText
到这一行的字节数。字节数为4(“测试”)+5(“你好”)+6(“世界!”=15
当两行在不同的.o或.obj文件中时,您可以不控制两行之间有多少字节,因为“ld”可能会将属于不同对象文件的代码放在内存中的任何位置
因此,即使您使用了一些(假设的)文件格式来支持这种重新定位,TestStringLen
的值也不是您期望的值
那怎么办呢?
不幸的是,我不知道“nasm”,但其他汇编程序允许生成“绝对符号”
在这种情况下,在一个文件中执行以下操作:
GLOBAL SomeText
GLOBAL SomeTextLen
...
SomeText db "Mein Beispieltext"
SomeTextLen equ $-SomeText
在另一个文件中,只需执行以下操作:
EXTERN SomeText
EXTERN SomeTextLen
如果不支持“绝对符号”,则必须执行以下操作:
GLOBAL SomeText
GLOBAL SomeTextLen
...
SomeText db "Mein Beispieltext"
SomeTextLen dd $-SomeText
以及:
请显示您的整个
main.asm
。我不明白为什么第46行是TestStringLen eq$-TestString
,而您似乎是在第4行这样做的。执行ld-o hexlib hexlib.o-melf\u i386
也没有任何意义。这试图创建一个名为hexlib
的程序,但您实际上只关心对象已生成的文件,以便以后可以将其与main.o
链接。基本上,您甚至不需要使用此命令。关于TestStringLen eq$-TestString
。这将不起作用,因为TestString
在另一个文件中定义,其地址在链接时才知道。您不能将此值用作常量(在EQU中)在更新的代码中,您现在有了TestStringLen EQU$-Ten
在哪里定义了Ten
?为了清晰起见,我刚刚更改了变量名称。我再次对其进行了适当编辑。该死!我真的希望这与段寄存器有关。我认为这是一个很好的开始。谢谢!