linux能运行汇编语言吗,Linux 环境下汇编语言

Linux 汇编

Linux 环境下汇编语言

By Phillip

翻译:Yijian

介绍:

Intel 和 AT&T的汇编语法格式

在Intel的汇编语法格式里寄存器前缀,而 AT&T汇编语法格式寄存器则有 ‘%’ 前缀,立即数前面要有前缀’$’

在Intel的汇编语法格式里十六进制和字节立即数风别用加’h’和’b’后缀。并且如果十六进制的第一个数字是字母的话,这个值就需要加一个前缀‘0’。

例子:

Intel格式

mov eax,1

mov ebx,0ffh

int 80h AT&T格式

movl $1,%eax

movl $0xff,%ebx

int  $0x80

操作数发方向

AT&T 和 Intel 格式中的源操作数和目标操作数的位置正好相反。在 Intel 汇编格式中,目标操作数在源操作数的左边;而在 AT&T 汇编格式中,目标操作数在源操作数的右边,我们通常从左到右阅读,AT&T汇编格式的用起来比较自然,这可能是它的优点

例子:

Intex 格式

指令 dest,source

mov eax,[ecx] AT&T 格式

指令  source,dest

movl (%ecx),%eax

内存操作

内存操作Intel和AT&T也是不一样。在Intel汇编格式基寄存器都用’[‘和’]’关闭,而AT&T格式用’(‘和’)’

例子:

Intex 格式

mov eax,[ebx]

mov eax,[ebx+3] AT&T 格式

movl (%ebx),%eax

movl 3(%ebx),%eax

系统调用

1 参数小于6的系统调用

对于所有的系统调用,寄存器 eax 中存放的是系统调用的功能号.如果系统调用的参数小于6个。按顺序存放在ebx,ecx,edx,esi,edi五个寄存器里。返回值存储在eax里

系统调用的功能号在/usr/include/sys/syscall.h下面。

例子:

$ cat write.s

.include "defines.h"

.data

hello:

.string "hello world/n"

.globl main

main:

movl $SYS_write,%eax

movl $STDOUT,%ebx

movl $hello,%ecx

movl $12,%edx

int $0x80

ret

2.系统调用的参数大与5

功能号仍然放在eax.但是参数放在连续的内存里了,并且指向第一个参数的指针的值放到ebx寄存器里。

如果你用堆栈的话,参数必须从最后一个到第一个一次push到堆栈里。堆栈的指针应该放到ebx里。

例如:

(mmap being the example syscall). Using mmap() in C:

#include

#include

#include

#include

#include

#define STDOUT 1

void main(void) {

char file[]="mmap.s";

char *mappedptr;

int fd,filelen;

fd=fopen(file, O_RDONLY);

filelen=lseek(fd,0,SEEK_END);

mappedptr=mmap(NULL,filelen,PROT_READ,MAP_SHARED,fd,0);

write(STDOUT, mappedptr, filelen);

munmap(mappedptr, filelen);

close(fd);

}

Arrangement of mmap() args in memory:

%esp %esp+4 %esp+8 %esp+12 %esp+16 %esp+20

00000000 filelen 00000001 00000001 fd 00000000

ASM Equivalent:

$ cat mmap.s

.include "defines.h"

.data

file:

.string "mmap.s"

fd:

.long  0

filelen:

.long  0

mappedptr:

.long  0

.globl main

main:

push %ebp

movl %esp,%ebp

subl $24,%esp

// open($file, $O_RDONLY);

movl $fd,%ebx // save fd

movl %eax,(%ebx)

// lseek($fd,0,$SEEK_END);

movl $filelen,%ebx // save file length

movl %eax,(%ebx)

xorl %edx,%edx

// mmap(NULL,$filelen,PROT_READ,MAP_SHARED,$fd,0);

movl %edx,(%esp)

movl %eax,4(%esp) // file length still in %eax

movl $PROT_READ,8(%esp)

movl $MAP_SHARED,12(%esp)

movl $fd,%ebx // load file descriptor

movl (%ebx),%eax

movl %eax,16(%esp)

movl %edx,20(%esp)

movl $SYS_mmap,%eax

movl %esp,%ebx

int $0x80

movl $mappedptr,%ebx // save ptr

movl %eax,(%ebx)

//  write($stdout, $mappedptr, $filelen);

// munmap($mappedptr, $filelen);

// close($fd);

movl %ebp,%esp

popl %ebp

ret

$

Socket网络编程的系统调用

Socket系统调用只有一个功能号放到eax里。Socket函数次功能号在/usr/include/linux/net.h里,并且放到ebx里。指向参数的指针放到ecx里。Socket的系统调用仍然是通过int $0x80执行

$ cat socket.s

.include "defines.h"

.globl _start

_start:

pushl %ebp

movl %esp,%ebp

sub $12,%esp

// socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);

movl $AF_INET,(%esp)

movl $SOCK_STREAM,4(%esp)

movl $IPPROTO_TCP,8(%esp)

movl $SYS_socketcall,%eax

movl $SYS_socketcall_socket,%ebx

movl %esp,%ecx

int $0x80

movl  $SYS_exit,%eax

xorl  %ebx,%ebx

int  $0x80

movl %ebp,%esp

popl %ebp

ret

$

命令行参数

在 Linux 操作系统中,当一个可执行程序通过命令行启动时,其所需的参数将被保存到栈中:首先是 argc,然后是指向各个命令行参数的指针数组 argv,最后是指向环境变量的指针数据 envp。在编写汇编语言程序时,很多时候需要对这些参数进行处理,下面的代码示范了如何在汇编代码中进行命令行参数的处理:

例如:

/* args.s */

.text

.globl _start

_start:

popl %ecx  // argc

lewp:

popl %ecx  // argv

test  %ecx,%ecx

jz exit

movl %ecx,%ebx

xorl %edx,%edx

strlen:

movb (%ebx),%al

inc %edx

inc %ebx

test %al,%al

jnz strlen

movb $10,-1(%ebx)

//  write(1,argv[i],strlen(argv[i]));

movl $SYS_write,%eax

movl $STDOUT,%ebx

int $0x80

jmp lewp

exit:

movl $SYS_exit,%eax

xorl %ebx,%ebx

int  $0x80

ret

GCC 嵌套汇编

GCC基本的嵌套汇编非常明了,基本的格式如下:

__asm__("movl %esp,%eax");

或者:

__asm__("

movl $1,%eax  // SYS_exit

xor %ebx,%ebx

int $0x80

");

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值