String 常量字符串保存在程序集中的什么位置?
当我在程序集中声明字符串时,如下所示:String 常量字符串保存在程序集中的什么位置?,string,assembly,memory,x86,String,Assembly,Memory,X86,当我在程序集中声明字符串时,如下所示: string DB "My string", 0 字符串保存在哪里? 声明它时,我可以确定它将保存在哪里吗?db将输出字节汇编到输出文件中的当前位置。您可以精确控制它们的去向 没有对任何其他位置的间接或引用,这就像char string[]=“blah blah”,而不是char*string=“blah blah”(但结尾没有隐式的零字节,这就是为什么必须使用,0来显式添加一个。) 当针对现代操作系统时(即不制作引导扇区或其他东西),您的代码+数据将
string DB "My string", 0
字符串保存在哪里?
声明它时,我可以确定它将保存在哪里吗?
db
将输出字节汇编到输出文件中的当前位置。您可以精确控制它们的去向
没有对任何其他位置的间接或引用,这就像char string[]=“blah blah”
,而不是char*string=“blah blah”
(但结尾没有隐式的零字节,这就是为什么必须使用,0
来显式添加一个。)
当针对现代操作系统时(即不制作引导扇区或其他东西),您的代码+数据将最终保存在目标文件中,然后链接到可执行文件或库中 在Linux(或其他ELF平台)上,将只读常量数据(包括字符串)放入
部分。rodata
。链接后,此部分(以及放置代码的部分.text
)成为文本段的一部分
Windows显然使用了section.rdata
不同的汇编器有不同的语法来更改节,但我认为节。在大多数使用DB
来处理数据字节的汇编器中,任何都可以工作
10个字符是来自put
的返回值,这是来自main的返回值,因为我们tail调用了它,它成为我们程序的退出状态。(Linux glibcput
显然在这种情况下返回字符计数。但手册只说它在成功时返回非负数,所以不要指望这个)
我用string
和mov
的绝对地址代替了RIP相对LEA
您可以使用readelf-a.out
或nm
查看可执行文件中的内容。db
将输出字节汇编到输出文件中的当前位置。您可以精确控制它们的去向
没有对任何其他位置的间接或引用,这就像char string[]=“blah blah”
,而不是char*string=“blah blah”
(但结尾没有隐式的零字节,这就是为什么必须使用,0
来显式添加一个。)
当针对现代操作系统时(即不制作引导扇区或其他东西),您的代码+数据将最终保存在目标文件中,然后链接到可执行文件或库中
在Linux(或其他ELF平台)上,将只读常量数据(包括字符串)放入部分。rodata
。链接后,此部分(以及放置代码的部分.text
)成为文本段的一部分
Windows显然使用了section.rdata
不同的汇编器有不同的语法来更改节,但我认为节。在大多数使用DB
来处理数据字节的汇编器中,任何都可以工作
10个字符是来自put
的返回值,这是来自main的返回值,因为我们tail调用了它,它成为我们程序的退出状态。(Linux glibcput
显然在这种情况下返回字符计数。但手册只说它在成功时返回非负数,所以不要指望这个)
我用string
和mov
的绝对地址代替了RIP相对LEA
您可以使用readelf-a.out
或nm
查看可执行文件中的内容。您的代码将告诉您它将在哪里。根据汇编程序的不同,有不同的方法。你能详细说明一下标题中的“const strings”和问题中的字节声明(这只是定义字节值;没有特别的方式显示“const”特性)是什么意思吗。若在公共数据段中的公共程序集中执行该操作,则可以在运行时修改该内存。x86上的运行时“const”是通过将内存布局组织到不同的页面中,并将包含“const”数据的页面设置为只读访问来实现的。也可以只存在编译时“const”,比如MASM,或者两者都存在,比如C/C++。不清楚你在问什么。@Ped7g他不能简单地写mov-si,offset-string
si寄存器将存储字符串的偏移量。现在有了DS:SI寄存器,他可以在内存中找到他的字符串。@Ahtisham是的,你可以通过TASM/MASM中的地址来获得内存地址。但这并没有说明在源代码编写过程中声明它的地方。实际上,您可以通过在源代码中的适当位置声明字符串,来有意地定位字符串在二进制文件中“land”的位置。如果你想把它放在“数据”部分,你必须在“数据”部分声明它,等等。。。作为程序员,您可以(几乎)完全控制从汇编程序发出的机器代码,因此您可以通过在源代码的所需部分声明来确定将保存到哪里。要得到它的确切地址就是这么简单的mov
。@Ahtisham不,你在回答别的问题,而不是OPs问题。您的指令在运行时获取地址。OP的问题是,如何有意识地设计,数据将“降落”在二进制中的什么位置,以及是否有可能影响到这一点(至少我是这样理解这个问题的,它不是很清楚)。您的代码将告诉它将在哪里。根据汇编程序的不同,有不同的方法。你能详细说明一下标题中的“const strings”和问题中的字节声明(这只是定义字节值;没有特别的方式显示“const”特性)是什么意思吗。若在公共数据段中的公共程序集中执行该操作,则可以在运行时修改该内存。x86上的运行时“const”是通过将内存布局组织到不同的页面中,并将包含“const”数据的页面设置为只读访问来实现的。也可以只存在编译时“const”,就像MASM一样,
;; NASM source for the x86-64 System V ABI.
section .rodata ; use section .rdata on Windows
string DB "My string", 0
section .data
static_storage_for_something: dd 123 ; one dword with value = 123
;; usually you don't need .data and can just use registers or the stack
section .bss ; zero-initialized memory, bytes not stored in the executable, just size
static_array: resd 12300000 ;; 12300000 dwords with value = 0
section .text
extern puts ; defined in libc
global main
main:
mov edi, string ; RDI = address of string = first function arg
;mov [rdi], 1234 ; would segfault because .rodata is mapped read-only
jmp puts ; tail-call puts(string)
peter@volta:/tmp$ cat > string.asm
(and paste the above, then press control-D)
peter@volta:/tmp$ nasm -f elf64 string.asm && gcc -no-pie string.o && ./a.out
My string
peter@volta:/tmp$ echo $?
10