我在NASM中有以下"uppercaser.asm"汇编程序,它将用户输入的所有小写字母转换为大写字母:
section .bss
Buff resb 1
section .data
section .text
global _start
_start:
nop ; This no-op keeps the debugger happy
Read: mov eax,3 ; Specify sys_read call
mov ebx,0 ; Specify File Descriptor 0: Standard Input
mov ecx,Buff ; Pass offset of the buffer to read to
mov edx,1 ; Tell sys_read to read one char from stdin
int 80h ; Call sys_read
cmp eax,0 ; Look at sys_read's return value in EAX
je Exit ; Jump If Equal to 0 (0 means EOF) to Exit
; or fall through to test for lowercase
cmp byte [Buff],61h ; Test input char against lowercase 'a'
jb Write ; If below 'a' in ASCII chart, not lowercase
cmp byte [Buff],7Ah ; Test input char against lowercase 'z'
ja Write ; If above 'z' in ASCII chart, not lowercase
; At this point, we have a lowercase character
sub byte [Buff],20h ; Subtract 20h from lowercase to give uppercase...
; ...and then write out the char to stdout
Write: mov eax,4 ; Specify sys_write call
mov ebx,1 ; Specify File Descriptor 1: Standard output
mov ecx,Buff ; Pass address of the character to write
mov edx,1 ; Pass number of chars to write
int 80h ; Call sys_write...
jmp Read ; ...then go to the beginning to get another character
Exit: mov eax,1 ; Code for Exit Syscall
mov ebx,0 ; Return a code of zero to Linux
int 80H ; Make kernel call to exit program
然后,该程序与调试器的-g -F stabs
选项组装在一起,并链接到ubuntu 18.04中的32位可执行文件。
对段运行readelf --segments uppercaser
,对节运行readelf -S uppercaser
,我看到文本段和文本节的大小不同。
readelf --segments uppercaser
Elf file type is EXEC (Executable file)
Entry point 0x8048080
There are 2 program headers, starting at offset 52
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x000000 0x08048000 0x08048000 0x000db 0x000db R E 0x1000
LOAD 0x0000dc 0x080490dc 0x080490dc 0x00000 0x00004 RW 0x1000
Section to Segment mapping:
Segment Sections...
00 .text
01 .bss
readelf -S uppercaser
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .text PROGBITS 08048080 000080 00005b 00 AX 0 0 16
[ 2] .bss NOBITS 080490dc 0000dc 000004 00 WA 0 0 4
[ 3] .stab PROGBITS 00000000 0000dc 000120 0c 4 0 4
[ 4] .stabstr STRTAB 00000000 0001fc 000011 00 0 0 1
[ 5] .comment PROGBITS 00000000 00020d 00001f 00 0 0 1
[ 6] .shstrtab STRTAB 00000000 00022c 00003e 00 0 0 1
[ 7] .symtab SYMTAB 00000000 0003d4 0000f0 10 8 11 4
[ 8] .strtab STRTAB 00000000 0004c4 000045 00 0 0 1
在节描述中,可以看到.text节的大小是5Bh
=91字节(与size
命令得到的数字相同(,而在段描述中,我们看到大小是0x000DB
,相差128字节。为什么?
来自Elf32_Phdr(程序头(结构的精灵手册页面:
p_filesz此成员保存的文件映像中的字节数片段。它可能是零。
p_memsz此成员保存内存映像中的字节数分段的。它可能是零。
这种差异在某种程度上与.bss部分有关吗?
请注意,文件地址0处的第一个程序段从虚拟地址0x08048000
开始,而不是从与.text部分对应的VA0x08048080
开始。
事实上,readelf显示为00 .text
的段包括ELF文件头(52字节(、对齐、两个程序头(2*32字节(和.text部分的netto内容,所有这些都从文件地址0映射到VA0x08048000
。