免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1138 | 回复: 0
打印 上一主题 下一主题

linux下使用汇编语言 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-09-13 16:25 |只看该作者 |倒序浏览
intel语AT&T语法
前缀
AT&T语法寄存器前要加%,立即数前要加$。intel语法的16进制数和2进制数后加'h'和'b'。16进制数第一个如果为字母,在需要加前缀0。
Intex Syntax
mov        eax,1
mov        ebx,0ffh
int        80h
AT&T Syntax
movl        $1,%eax
movl        $0xff,%ebx
int         $0x80
指令的方向,intel从右往左,AT&T从左往右
Intex Syntax
instr        dest,source
mov        eax,[ecx]
AT&T Syntax
instr         source,dest
movl        (%ecx),%eax
内存操作
intel基自寄存器在[]里面,AT&T在()里面
Intex Syntax
mov        eax,[ebx]
mov        eax,[ebx+3]
AT&T Syntax
movl        (%ebx),%eax
movl        3(%ebx),%eax
intel语法segreg:[base+index*scale+disp]
AT&T语法%segreg:disp(base,index,scale)
index/scale/disp/segreg都是可选的,scale,如果没有选,如果选了index那么scale默认为1
segreg要看是在实模式还是保护模式。AT&T如果scale/disp是立即数,不加$前缀。
Intel Syntax
instr         foo,segreg:[base+index*scale+disp]
mov        eax,[ebx+20h]
add        eax,[ebx+ecx*2h
lea        eax,[ebx+ecx]
sub        eax,[ebx+ecx*4h-20h]
AT&T Syntax
instr        %segreg:disp(base,index,scale),foo
movl        0x20(%ebx),%eax
addl        (%ebx,%ecx,0x2),%eax
leal        (%ebx,%ecx),%eax
subl        -0x20(%ebx,%ecx,0x4),%eax
intel byte ptr,word ptr dword ptr
AT&T,b,w,l   movb movw movl
Intel Syntax
mov        al,bl
mov        ax,bx
mov        eax,ebx
mov        eax, dword ptr [ebx]
AT&T Syntax
movb        %bl,%al
movw        %bx,%ax
movl        %ebx,%eax
movl        (%ebx),%eax
对于小于6个参数的系统调用,参数传递顺序是%ebx,%ecx,%edx,%esi,%edi
对于大于5个参数的系统调用,参数存放在内存中,且%ebx指向内存地址,如果在栈中,参数反向入栈,结果是第一个参数在栈顶,%ebx指向栈顶。否则,将参数拷贝到分配的内存处,%ebx指向首地址。
Example:
(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
00000000filelen00000001
00000001fd00000000
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系统调用
root@administrator-laptop:~# cat /usr/include/asm/unistd_32.h|grep socket
#define __NR_socketcall        102
socket只使用102这个系统调用号,放在%eax中,子函数号可以在/usr/include/linux/net.h中查到,放在%ebx中,参数指针放在%ecx中,通过$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
$
GCC内嵌汇编
        __asm__("" : output : input : modify);
#include
int main(void) {
        int foo=10,bar=15;
       
        __asm__ __volatile__ ("addl         %%ebxx,%%eax"
                : "=eax"(foo)                 // ouput
                : "eax"(foo), "ebx"(bar)// input
                : "eax"                        // modify
        );
        printf("foo+bar=%d\n", foo);
        return 0;
}
$
__volatile__防止汇编指令被删除。
Abbrev Table
AbbrevRegister
a%eax/%ax/%al
b%ebx/%bx/%bl
c%ecx/%cx/%cl
d%edx/%dx/%dl
S%esi/%si
D%edi/%di
mmemory
$ cat inline2.c
int main(void) {
        long eax;
        short bx;
        char cl;
        __asm__("nop;nop;nop"); // to separate inline asm from the rest of
                                // the code
        __volatile__ __asm__("
                test        %0,%0
                test        %1,%1
                test        %2,%2"
                : /* no outputs */
                : "a"((long)eax), "b"((short)bx), "c"((char)cl)
        );
        __asm__("nop;nop;nop");
        return 0;
}
$ gcc -o inline2 inline2.c
$ gdb ./inline2
GNU gdb 4.18
Copyright 1998 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i686-pc-linux-gnulibc1"...
(no debugging symbols found)...
(gdb) disassemble main
Dump of assembler code for function main:
... start: inline asm ...
0x8048427 : nop
0x8048428 : nop
0x8048429 : nop
0x804842a : mov 0xfffffffc(%ebp),%eax
0x804842d : mov 0xfffffffa(%ebp),%bx
0x8048431 : mov 0xfffffff9(%ebp),%cl
0x8048434 : test %eax,%eax
0x8048436 : test %bx,%bx
0x8048439 : test %cl,%cl
0x804843b : nop
0x804843c : nop
0x804843d : nop
... end: inline asm ...
End of assembler dump.
$
"q"允许编译器选择a,b,c,d寄存器
$ cat inline3.c
#include
int main(void) {
        long eax=1,ebx=2;
        __asm__ __volatile__ ("add %0,%2"
                : "=b"((long)ebx)
                : "a"((long)eax), "q"(ebx)
                : "2"
        );
        printf("ebx=%x\n", ebx);
        return 0;
}
$
编译时加-s选项可以减小生成的程序大小


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u2/70469/showart_1190586.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP