LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 888|回复: 2

3个汇编的问题求教。

[复制链接]
发表于 2010-6-11 15:13:28 | 显示全部楼层 |阅读模式
1:
        在64位机器上压栈的时候一定要把整个寄存器的值压入,不能够只压入其中的32位?
        我正在看的汇编是32位的,然后32位的代码在64位的机器上居然用汇编器通不过。我印象中应该是向下兼容的啊,就像32位的兼容16位的一样,当只需要16位的时候就只要使用寄存器ax,要32位的时候才eax。push指令应该可以把任何值压入堆栈的吧,在64位的机器上压栈的时候却一定要把整个寄存器的值压入,不能够只压入其中的32位(pushl %eax报错,一定要pushq %rax才行)。这是怎么回事?

2:
        不同的系统调用值却能够正常工作?
        书上说Linux的系统调用及其编号在/usr/include/asm/unistd.h中包含了。于是我在64位系统上打开了这个文件,却看到几行宏定义。
                unistd.h:
                # ifdef __i386__
                #  include "unistd_32.h"
                # else
                #  include "unistd_64.h"
                # endif
        于是我打开了unistd_32.h。
                unistd_32.h(一部分):
                        #ifndef _ASM_X86_UNISTD_32_H
                        #define _ASM_X86_UNISTD_32_H

                        /*
                         * This file contains the system call numbers.
                         */

                        #define __NR_restart_syscall      0
                        #define __NR_exit                  1
                        #define __NR_fork                  2
                        #define __NR_read                  3
                        #define __NR_write                  4
                        #define __NR_open                  5
                        #define __NR_close                  6
                        #define __NR_waitpid                  7
                        #define __NR_creat                  8
                        #define __NR_link                  9
        这个跟书上说的一样,exit的系统调用是1。
        之后我打开了unistd_64.h。
                unistd_64.h(一部分):
                        #ifndef _ASM_X86_UNISTD_64_H
                        #define _ASM_X86_UNISTD_64_H

                        #ifndef __SYSCALL
                        #define __SYSCALL(a, b)
                        #endif

                        /*
                         * This file contains the system call numbers.
                         *
                         * Note: holes are not allowed.
                         */

                        /* at least 8 syscall per cacheline */
                        #define __NR_read                                0
                        __SYSCALL(__NR_read, sys_read)
                        #define __NR_write                                1
                        __SYSCALL(__NR_write, sys_write)
                        #define __NR_open                                2
                        __SYSCALL(__NR_open, sys_open)
                        #define __NR_close                                3
                        __SYSCALL(__NR_close, sys_close)
                        #define __NR_stat                                4
                        __SYSCALL(__NR_stat, sys_newstat)
                        #define __NR_fstat                                5
                        __SYSCALL(__NR_fstat, sys_newfstat)
                        #define __NR_lstat                                6
        这看起来在64位系统上系统调用exit的编号不是1。
        但是我用包含下面的指令的32位汇编程序在32位机器上汇编并链接出来的程序在64位机器上却能够正常运行?
                functest3.s(结尾部分):
                        movl $1 %eax
                        movl $0 %ebx
                        int 0x80
        gdb调试信息(64位机器上):
                lucifer@cross:~/Desktop/test$ gdb -q  ./functest3_32
                Reading symbols from /home/lucifer/Desktop/test/functest3_32...(no debugging symbols found)...done.
                (gdb) r
                Starting program: /home/lucifer/Desktop/test/functest3_32

                Program exited normally.
                (gdb) q
                lucifer@cross:~/Desktop/test$

3:
        同样的C代码为什么在64位的机器上汇编出来的汇编程序的行数比在32位机器上汇编出来的程序的行数要多?要运行的指令多了速度还能更快?多出来的代码是在干什么?
        tmp3.c:
                #include <stdio.h>

                int add(int a,int b);
                int
                main()
                {
                   int ret = add(2,3);
                   return 0;
                }


                int
                add(int a,int b)
                {
                   int i = 4;
                   return a+b+i;
                }
        32位机器上汇编出来的程序源码:
        tmp3_32.s(共33行):
                        .file        "tmp3.c"
                                .text
                        .globl main
                                .type        main, @function
                        main:
                                pushl        %ebp
                                movl        %esp, %ebp
                                andl        $-16, %esp
                                subl        $32, %esp
                                movl        $3, 4(%esp)
                                movl        $2, (%esp)
                                call        add
                                movl        %eax, 28(%esp)
                                movl        $0, %eax
                                leave
                                ret
                                .size        main, .-main
                        .globl add
                                .type        add, @function
                        add:
                                pushl        %ebp
                                movl        %esp, %ebp
                                subl        $16, %esp
                                movl        $4, -4(%ebp)
                                movl        12(%ebp), %eax
                                movl        8(%ebp), %edx
                                leal        (%edx,%eax), %eax
                                addl        -4(%ebp), %eax
                                leave
                                ret
                                .size        add, .-add
                                .ident        "GCC: 4.4.3"
                                .section        .note.GNU-stack,"",@progbits
        64位机器上汇编出来的程序源码:
        tmp3_64.s(共47行):
                        .file        "tmp3.c"
                                .text
                        .globl main
                                .type        main, @function
                        main:
                        .LFB0:
                                .cfi_startproc
                                pushq        %rbp
                                .cfi_def_cfa_offset 16
                                movq        %rsp, %rbp
                                .cfi_offset 6, -16
                                .cfi_def_cfa_register 6
                                subq        $16, %rsp
                                movl        $3, %esi
                                movl        $2, %edi
                                call        add
                                movl        %eax, -4(%rbp)
                                movl        $0, %eax
                                leave
                                ret
                                .cfi_endproc
                        .LFE0:
                                .size        main, .-main
                        .globl add
                                .type        add, @function
                        add:
                        .LFB1:
                                .cfi_startproc
                                pushq        %rbp
                                .cfi_def_cfa_offset 16
                                movq        %rsp, %rbp
                                .cfi_offset 6, -16
                                .cfi_def_cfa_register 6
                                movl        %edi, -20(%rbp)
                                movl        %esi, -24(%rbp)
                                movl        $4, -4(%rbp)
                                movl        -24(%rbp), %eax
                                movl        -20(%rbp), %edx
                                leal        (%rdx,%rax), %eax
                                addl        -4(%rbp), %eax
                                leave
                                ret
                                .cfi_endproc
                        .LFE1:
                                .size        add, .-add
                                .ident        "GCC: 4.4.3"
                                .section        .note.GNU-stack,"",@progbits
 楼主| 发表于 2010-6-27 23:36:56 | 显示全部楼层
我我顶顶顶顶。
回复 支持 反对

使用道具 举报

发表于 2010-7-1 20:53:47 | 显示全部楼层
1、pushl %eax在64位下不能用,只能pushq这点指令手册有说明,amd 64实物没出之前用simics时验证过;
2、32位程序和64位程序对应的系统调用入口不同,所以命令码完全可以重新定义。FreeBSD通过调用上下文机制还可以同时执行Linux程序,原理也与之类似;
3、二者生成的指令基本一样,并非64位代码速度必然超过32位。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表