Linux下Asm汇编,链接,debug

32位

32bit cpuid as+ld 
32bit hello nasm+ld
32bit hello gcc+ld

64位

64bit cpuid as+ld   
64bit hello as+ld
64bit hello nasm+ld

生成64bit ELF

调用号文件:
/usr/include/asm/unistd_32.h
/usr/include/asm/unistd_64.h
	

vim eatsyscall.asm

SECTION .data
EatMsg: db "Eat at Joe's!",10
EatLen: equ $-EatMsg
SECTION .bss
SECTION .text
global _start
_start:
		nop
		mov eax,4
		mov ebx,1
		mov ecx,EatMsg
		mov edx,EatLen
		int 80H
		mov eax,1
		mov ebx,0
		int 80H
unix>nasm -f elf64 -g -F stabs eatsyscall.asm
unix>ld -o eatsyscall eatsyscall.o
[dark@peak ch4AsmRight]$file eatsyscall
eatsyscall: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, not stripped

gcc生成32bit ELF

源文件为c语言,用gcc生成32bit ELF

假设makefile中有一个target叫p.

[ice@icefire ch7Link]$make p
gcc -Wall -g -O2 -c -m32 -o main.o main.c
gcc -Wall -g -O2 -c -m32 -o swap.o swap.c
gcc -Wall -g -O2 -m32 -o p main.o swap.o
[ice@icefire ch7Link]$file main.o
main.o: ELF 32-bit LSB relocatable, Intel 80386, version 1 (SYSV), not stripped
[ice@icefire ch7Link]$file swap.o
swap.o: ELF 32-bit LSB relocatable, Intel 80386, version 1 (SYSV), not stripped
[ice@icefire ch7Link]$file p
p: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=3033cdebf2b6130fa4aba2f5c640bbe67d6c1d81, not stripped
	

intel语法汇编,用nasm+ld

源文件为eatsyscall.asm

nasm -f elf32 -g -F stabs eatsyscall.asm
ld -m elf_i386 -o eatsyscall eatsyscall.o
[dark@peak ch4AsmRight]$file eatsyscall
eatsyscall: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, not stripped
参考:ld生成32bit ELF

intel语法,用nasm+gcc

vim hello.asm

用gcc时候是入口是main而不是_start

	section .data
msg:
	db "hello,world",10
	len equ $-msg

	section .text
	global main
main:
	mov edx, len
	mov ecx, msg
	mov ebx,1
	mov eax,4 ;直接使用sys_write系统调用

	int 0x80
	mov ebx,0
	mov eax,1
	int 0x80
nasm -f elf -g -F stabs -o hello.o hello.asm
gcc -m32 -g -o hello hello.o
[dark@peak]$file hello
hello: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.32, not stripped

AT&T语法,GNU as+ld 实现32bit

[dark@peak ch3Sample]vim cpuid.s
.section .data
output:
	.ascii "The processor Vendor ID is ‘xxxxxxxxxxxx’\n"

.section .text
.global _start
_start:
	movl $0,	%eax
	cpuid
	movl $output, %edi

	movl %ebx,	28(%edi)
	movl %edx,	32(%edi)
	movl %ecx,	36(%edi)
#系统调用
	movl $4,	%eax
	movl $1,	%ebx
	movl $output,%ecx
	movl $42,	%edx
	int	$0x80
#系统调用结束,退出程序
	movl $1,	%eax
	movl $0,	%ebx
	int	$0x80
as --32 cpuid.s -o cpuid.o
ld -m elf_i386 -o cpuid cpuid.o
[dark@peak ch3Sample]$file cpuid
cpuid: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, not stripped

PS: as的注释风格GNU汇编器

1

调用约定
wikipedia:https://en.wikipedia.org/wiki/Calling_convention

	

cdel, gcc, ia-32(i386)

例子: 主调函数 功能函数 3种方式去make: @1: obj: as, elf: ld, 不需要动态库的情况,比较好的解决方案 + as --32 -gstabs mymath.s -o obj/mymath.o + as --32 -gstabs myfun.s -o obj/myfun.o + ld -emain -m elf_i386 -dynamic-linker /lib/ld-linux.so.2 obj/myfun.o obj/mymath.o -o myfun.bin -lc @2:obj: gcc -m32, elf: ld. 需要把汇编功能函数编译成共享库的解决方案 + gcc -m32 -fPIC -c mymath.s -o obj/mymath.o + gcc -m32 -shared obj/mymath.o -o obj/libmymath.so + gcc -m32 -c myfun.s -o obj/myfun.o + ld -emain -m elf_i386 -dynamic-linker /lib/ld-linux.so.2 obj/myfun.o -o myfun.bin -lc -L obj/ -lmymath @3: obj: gcc -m32, elf: gcc -m32,这个阶段有警告,目前不知道原因 + gcc -m32 -fPIC -c mymath.s -o obj/mymath.o + gcc -m32 -fPIC -c myfun.s -o obj/myfun.o + gcc -m32 -fPIC obj/myfun.o obj/mymath.o -o bin/myfun.elf /usr/lib/gcc/x86_64-pc-linux-gnu/7.3.0/../../../../x86_64-pc-linux-gnu/bin/ld: obj/myfun.o: warning: relocation in readonly section `.text' /usr/lib/gcc/x86_64-pc-linux-gnu/7.3.0/../../../../x86_64-pc-linux-gnu/bin/ld: warning: creating a DT_TEXTREL in a shared object.

在fedora24-x86_64中编译32bit汇编程序的小问题

1:没有/lib/ld-linux.so.2
dnf install glibc.i686
2:
ld -m elf_i386 -dynamic-linker /lib/ld-linux.so.2 -lc signtest.o -o signtest
ld: cannot find -lc
对于libc这个动态库,名字必须要是libc.so,甚至连libc.so.6都是错误的
cd /lib/
ln -s libc-2.23.so libc.so

gdb debug Asm

参考blog:用gdb调试nasm汇编程序

下一条指令

nexti

some tips for gdb debug:

print multiple registers

(gdb) print {$eax,$ebx,$ecx}
$8 = {0, 350, 24420}

objdump使用

常用参数

[-D|--disassemble-all]
[-j section|--section=section]
[-r|--reloc] // 在看CSAPP的(链接) 章节的时候要看Elf32_Rel.type

NASM使用

db, dw, dd, dq
1   2    4   8 bytes

GAS使用

.float, .double占用长度

nteger types
.octa 16 bytes on x86_64 and x86
.quad 8 bytes on x86_64 and x86
.long and .int 4 bytes on x86_64 and x86
.word, .short and .hword 2 bytes on x86_64 and x86
.byte is, of course, 1 byte on x86_64 and x86
Floating-point types
.tfloat 10 bytes on x86_64 and x86
.double 8 bytes on x86_64 and x86
.single and .float 4 bytes on x86_64 and x86

后缀b,w,l,q

后缀含义
https://www3.nd.edu/~dthain/courses/cse40243/fall2015/intel-intro.html
Suffix	Name	Size
B	BYTE	1 byte (8 bits)
W	WORD	2 bytes (16 bits)
L	LONG	4 bytes (32 bits)
Q	QUADWORD	8 bytes (64 bits)
https://www3.nd.edu/~dthain/courses/cse40243/fall2015/intel-intro.html

.lcomm

http://web.mit.edu/gnu/doc/html/as_7.html
.lcomm symbol , length
Reserve length (an absolute expression) bytes for a local common denoted by symbol. The section and value of symbol are those of the new local common. The addresses are allocated in 
the bss section, so that at run-time the bytes start off zeroed. Symbol is not declared global (see section .global symbol, .globl symbol), so is normally not visible to ld.
The syntax for .lcomm differs slightly on the HPPA. The syntax is `symbol .lcomm, length'; symbol is optional.

.comm

http://web.mit.edu/gnu/doc/html/as_7.html#SEC97
.comm symbol , length
.comm declares a named common area in the bss section. Normally ld reserves memory addresses for it during linking, so no partial program defines the location of the symbol. 
Use .comm to tell ld that it must be at least length bytes long. ld allocates space for each .comm symbol that is at least as long as the longest .comm request in any of the partial 
programs linked. length is an absolute expression.
The syntax for .comm differs slightly on the HPPA. The syntax is `symbol .comm, length'; symbol is optional.

gas中重复一块指令许多次

.rept count

Repeat the sequence of lines between the .rept directive and the next .endr directive count times.
For example, assembling

.rept   3
.long   0
.endr

is equivalent to assembling

.long   0
.long   0
.long   0

gas中.comm指令

.comm name, size, alignment
alignment is optional 

nasm汇编器相关

times伪指令,重复某一指令若干次

times prefix for nasm

64位汇编与32位一些不同

 64位hello world 

nasm 相关

Quick review,
nasm的db dw dd
DB - Define Byte. 8 bits
DW - Define Word. Generally 2 bytes on a typical x86 32-bit system
DD - Define double word. Generally 4 bytes on a typical x86 32-bit system

浮点数传参规则

32bit系统浮点数:通过栈传参
C代码, gcc -S
手工打造的汇编代码

as, nasm, gdb标号处的值与地址表示

as:
eatMsg:
.ascii "abc\n"
得到标号地址:
movl $eatMsg, %ecx # ecx= addr of msg
桔标号处存的数:
movl eatMsg, %ecx # ecx = value: 0xa636261
nasm:
eatMsg:
db "abc",10
标号地址:
mov ecx, eatMsg
mov ecx, [eatMsg]
gdb:
p/x &eatMsg : addr of label
p/x eatMsg: value in label addr

gnu gas中字符串长度

https://stackoverflow.com/questions/64187905/gas-aarch64-syntax-to-get-ascii-string-length