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 <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>

#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
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值