x86汇编

Linux 汇编语言开发指南

movl %eax, %edx          #  edx = eax 寄存器寻址  , eax寄存器里的数据参与计算
movl $0x123, %edx        #  edx = 0x123; 立即数寻址 ,  数值0x123参与计算
movl 0x123, %edx         #  edx = *(int32_t*)0x123  直接寻址  , 0x123地址里的数值参与计算
movl (%ebx), %edx        #  edx = *(int32_t*)ebx 间接寻址   , ebx里的数值是地址,这个地址指向的数值参与计算
movl 4(%ebx), %edx       #  edx = *(int32_t*)(ebx+4)  变址寻址  ,  ebx里的数值+4 作为地址,这个地址指向的数值参与计算
pushl %eax  ; 

相当于{subl $4, %esp; movl %eax, (%esp); } , pushl 这个l 指Long,是32bits,intel栈是向下增长的,所以esp要减4. 参考函数栈EBP,ESP寄存器

popl %eax ; 

相当于{movl (%esp), %eax; addl $4, $esp;}

call 0x12345 ; 

相当于 { pushl %eip() ; movl $0x12345, %eip();} eip(*) 是不能被程序员直接修改的,只能通过指令,间接修改

汇编指令分析:

pushl $8                 ; (假设ebp,esp指向同一地址)ebp 指针不变;esp减4,向下前进
movl %esp, %ebp          ; ebp减4,和esp指向一致
pushl %esp               ; esp减4,向下移动一位
pushl $8                 ; esp减4,向下移动一位
addl $4, %esp            ; esp加4,向上回退一位
popl %esp                ; esp加4,向上回退一位

C程序编译成汇编

test1.c

int g(int x)
{
	return x+3;
}


int f(int x) {
	return g(x);
}

int main(void)
{
	return f(8) + 1;
}

gcc -S -o test1.s test1.c -m32

命令说明
-S 编译成汇编,
-m32 编译成32位汇编, uname -a 可以看到所在平台是linux-64位,我们研究的是 32位汇编
-o 生成目标文件的文件名

test1.s 文件:

	.file	"test1.c"
	.text
	.globl	g
	.type	g, @function
g:
.LFB0:
	.cfi_startproc
	pushl	%ebp
	.cfi_def_cfa_offset 8
	.cfi_offset 5, -8
	movl	%esp, %ebp
	.cfi_def_cfa_register 5
	movl	8(%ebp), %eax
	addl	$3, %eax
	popl	%ebp
	.cfi_restore 5
	.cfi_def_cfa 4, 4
	ret
	.cfi_endproc
.LFE0:
	.size	g, .-g
	.globl	f
	.type	f, @function
f:
.LFB1:
	.cfi_startproc
	pushl	%ebp
	.cfi_def_cfa_offset 8
	.cfi_offset 5, -8
	movl	%esp, %ebp
	.cfi_def_cfa_register 5
	subl	$4, %esp
	movl	8(%ebp), %eax
	movl	%eax, (%esp)
	call	g
	leave
	.cfi_restore 5
	.cfi_def_cfa 4, 4
	ret
	.cfi_endproc
.LFE1:
	.size	f, .-f
	.globl	main
	.type	main, @function
main:
.LFB2:
	.cfi_startproc
	pushl	%ebp
	.cfi_def_cfa_offset 8
	.cfi_offset 5, -8
	movl	%esp, %ebp
	.cfi_def_cfa_register 5
	subl	$4, %esp
	movl	$8, (%esp)
	call	f
	addl	$1, %eax
	leave
	.cfi_restore 5
	.cfi_def_cfa 4, 4
	ret
	.cfi_endproc
.LFE2:
	.size	main, .-main
	.ident	"GCC: (GNU) 4.8.5 20150623 (Red Hat 4.8.5-36)"
	.section	.note.GNU-stack,"",@progbits

以".“开头的都是链接时的辅助信息,不实际执行,可以将以”."开头的命令直接省去。

执行过程演示:
在这里插入图片描述

c语言中内嵌汇编:


#include<stdio.h>

int main(void)
{

    int input,output,temp;
    input = 1;
    __asm__ __volatile__ (
        "movl $0 , %%eax;\n\t"   // $0 是立即数
        "movl %%eax , %1;\n\t"   // %1 是二个输出参数,按照公式:"__asm__(汇编语句模板: 输出部分: 输入部分: 破坏描述部分)", %0 是output, %1是temp
        "movl $2 , %%eax;\n\t"
        "movl %%eax , %0;\n\t"   // %0 是第一个输出数 output
        :"=m"(output),"=m"(temp)
        :"r"(input)
        :"eax"
    );

    printf("%d %d\n", temp, output);

    return 0;
}

%%eax 第一个”%“是转义

内嵌汇编语法如下:

__asm__(汇编语句模板: 输出部分: 输入部分: 破坏描述部分)

共四个部分:汇编语句模板,输出部分,输入部分,破坏描述部分,各部分使用“:” 格开,汇编语句模板必不可少,其他三部分可选,如果使用了后面的部分,而前面部分为空, 也需要用“:”格开,相应部分内容为空。例如:

__asm__ __volatile__("cli": : :"memory")

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值