久久精品精选,精品九九视频,www久久只有这里有精品,亚洲熟女乱色综合一区
    分享

    匯編和c只有一步之近

     ShangShujie 2012-06-12

    作者:陳曦

    日期:2012-6-8 10:50:13

    環(huán)境:[Ubuntu 11.04  Intel-based x64 gcc4.5.2  CodeBlocks10.05  AT&T匯編  Intel匯編] 

    轉(zhuǎn)載請注明出處


    Q: 舉個例子吧。

    A: 下面的代碼的目標是計算1+2的值,最后放到變量temp中,并輸出:

    1. #include <stdio.h>  
    2. #include <string.h>  
    3.   
    4. #define PRINT_D(longValue)       printf(#longValue" is %ld\n", ((long)longValue));  
    5. #define PRINT_STR(str)              printf(#str" is %s\n", (str));  
    6.   
    7.   
    8. static void assemble_func()  
    9. {  
    10.     int temp;  
    11.     __asm__("mov $1, %eax");  
    12.     __asm__("mov $2, %ebx");  
    13.     __asm__("add %ebx, %eax");  // 1 + 2  
    14.     __asm__("mov %%eax, %0":"=r"(temp));    // mov the value of register eax to the var "temp"   
    15.     PRINT_D(temp)               // print temp   
    16. }  
    17.   
    18. int main()  
    19. {  
    20.     assemble_func();  
    21.     return 0;  
    22. }  

    運行結(jié)果:
    1. temp is 3  

    Q: assemble_func函數(shù)的匯編代碼形式是什么?

    A: 

    1.   0x08048404 <+0>:    push   ebp  
    2.    0x08048405 <+1>:   mov    ebp,esp  
    3.    0x08048407 <+3>:   push   ebx  
    4.    0x08048408 <+4>:   sub    esp,0x24  
    5. => 0x0804840b <+7>:    mov    eax,0x1  
    6.    0x08048410 <+12>:  mov    ebx,0x2  
    7.    0x08048415 <+17>:  add    eax,ebx  
    8.    0x08048417 <+19>:  mov    ebx,eax  
    9.    0x08048419 <+21>:  mov    DWORD PTR [ebp-0xc],ebx  
    10.    0x0804841c <+24>:  mov    eax,0x8048510  
    11.    0x08048421 <+29>:  mov    edx,DWORD PTR [ebp-0xc]  
    12.    0x08048424 <+32>:  mov    DWORD PTR [esp+0x4],edx  
    13.    0x08048428 <+36>:  mov    DWORD PTR [esp],eax  
    14.    0x0804842b <+39>:  call   0x8048340 <printf@plt>  
    15.    0x08048430 <+44>:  add    esp,0x24  
    16.    0x08048433 <+47>:  pop    ebx  
    17.    0x08048434 <+48>:  pop    ebp  
    18.    0x08048435 <+49>:  ret      

    上面的匯編是在調(diào)試運行到assemble_func函數(shù)的開始時,使用disassemble命令得到的數(shù)據(jù)。注意第五行左側(cè)的箭頭符號是調(diào)試狀態(tài)顯示正在運行的行數(shù)。


    Q: 上面的匯編是內(nèi)嵌到c代碼中的,單獨完全的匯編代碼,如何實現(xiàn)hello world的功能?

    A: 從本質(zhì)上說,只用匯編的形式需要對于底層更了解,c代碼從編譯的角度來說和匯編沒什么區(qū)別,只是寫的格式以及調(diào)用的東西看起來不一致罷了。

    如下,是實現(xiàn)標準控制臺輸出功能的代碼:

    1. .section .rodata  
    2. str:  
    3. .ascii "Hello,world.\n"  
    4.   
    5. .section .text  
    6. .globl _main  
    7. _main:  
    8. movl  $4,    %eax    # the number of system call   
    9. movl  $1,    %ebx    # file descriptor, 1 means stdout  
    10. movl  $str,  %ecx    # string address  
    11. movl  $13,   %edx    # string length  
    12. int   $0x80  

    保存為hello.s.


    Q: 如何編譯它,使用gcc嗎?

    A: 當然可以,不過這個文件顯然不需要預處理了,它已經(jīng)是匯編格式了,不需要單純狹義的編譯過程了,只需要從匯編過程開始了。

    它可以直接生成目標文件hello.o


    Q: 接下來做什么?可以直接執(zhí)行它嗎?

    A: 試試。


    此時,給hello.o添加可執(zhí)行權限再執(zhí)行:


    Q: 這是為什么?

    A: 繼續(xù)觀察hello.o文件的屬性。

    可以看出,它還不是可執(zhí)行文件。其實很簡單,hello.o只是目標文件,并沒有鏈接成可執(zhí)行文件。


    Q: 這又是為什么?沒有找到入口符號_start, ld默認的入口符號是_start?

    A: 是的。在代碼中使用的是_main, 所以應該讓鏈接器明白,入口符號是_main.


    Q: 現(xiàn)在應該可以運行了吧。運行一下:

    Hello,world是輸出了,為什么后面會出現(xiàn)段錯誤呢?

    A: 我們首先看看上面的運行返回了什么。

    返回值為139,它代表什么?


    Q: 從系統(tǒng)的errno.h頭文件以及相關文件中查找,得到所有系統(tǒng)錯誤碼:

    /usr/include/asm-generic/errno-base.h文件:

    1. #ifndef _ASM_GENERIC_ERRNO_BASE_H  
    2. #define _ASM_GENERIC_ERRNO_BASE_H  
    3.   
    4. #define EPERM        1  /* Operation not permitted */  
    5. #define ENOENT       2  /* No such file or directory */  
    6. #define ESRCH        3  /* No such process */  
    7. #define EINTR        4  /* Interrupted system call */  
    8. #define EIO      5  /* I/O error */  
    9. #define ENXIO        6  /* No such device or address */  
    10. #define E2BIG        7  /* Argument list too long */  
    11. #define ENOEXEC      8  /* Exec format error */  
    12. #define EBADF        9  /* Bad file number */  
    13. #define ECHILD      10  /* No child processes */  
    14. #define EAGAIN      11  /* Try again */  
    15. #define ENOMEM      12  /* Out of memory */  
    16. #define EACCES      13  /* Permission denied */  
    17. #define EFAULT      14  /* Bad address */  
    18. #define ENOTBLK     15  /* Block device required */  
    19. #define EBUSY       16  /* Device or resource busy */  
    20. #define EEXIST      17  /* File exists */  
    21. #define EXDEV       18  /* Cross-device link */  
    22. #define ENODEV      19  /* No such device */  
    23. #define ENOTDIR     20  /* Not a directory */  
    24. #define EISDIR      21  /* Is a directory */  
    25. #define EINVAL      22  /* Invalid argument */  
    26. #define ENFILE      23  /* File table overflow */  
    27. #define EMFILE      24  /* Too many open files */  
    28. #define ENOTTY      25  /* Not a typewriter */  
    29. #define ETXTBSY     26  /* Text file busy */  
    30. #define EFBIG       27  /* File too large */  
    31. #define ENOSPC      28  /* No space left on device */  
    32. #define ESPIPE      29  /* Illegal seek */  
    33. #define EROFS       30  /* Read-only file system */  
    34. #define EMLINK      31  /* Too many links */  
    35. #define EPIPE       32  /* Broken pipe */  
    36. #define EDOM        33  /* Math argument out of domain of func */  
    37. #define ERANGE      34  /* Math result not representable */  
    38.   
    39. #endif  


    /usr/include/asm-generic/errno.h文件:

    1. #ifndef _ASM_GENERIC_ERRNO_H  
    2. #define _ASM_GENERIC_ERRNO_H  
    3.   
    4. #include <asm-generic/errno-base.h>  
    5.   
    6. #define EDEADLK     35  /* Resource deadlock would occur */  
    7. #define ENAMETOOLONG    36  /* File name too long */  
    8. #define ENOLCK      37  /* No record locks available */  
    9. #define ENOSYS      38  /* Function not implemented */  
    10. #define ENOTEMPTY   39  /* Directory not empty */  
    11. #define ELOOP       40  /* Too many symbolic links encountered */  
    12. #define EWOULDBLOCK EAGAIN  /* Operation would block */  
    13. #define ENOMSG      42  /* No message of desired type */  
    14. #define EIDRM       43  /* Identifier removed */  
    15. #define ECHRNG      44  /* Channel number out of range */  
    16. #define EL2NSYNC    45  /* Level 2 not synchronized */  
    17. #define EL3HLT      46  /* Level 3 halted */  
    18. #define EL3RST      47  /* Level 3 reset */  
    19. #define ELNRNG      48  /* Link number out of range */  
    20. #define EUNATCH     49  /* Protocol driver not attached */  
    21. #define ENOCSI      50  /* No CSI structure available */  
    22. #define EL2HLT      51  /* Level 2 halted */  
    23. #define EBADE       52  /* Invalid exchange */  
    24. #define EBADR       53  /* Invalid request descriptor */  
    25. #define EXFULL      54  /* Exchange full */  
    26. #define ENOANO      55  /* No anode */  
    27. #define EBADRQC     56  /* Invalid request code */  
    28. #define EBADSLT     57  /* Invalid slot */  
    29.   
    30. #define EDEADLOCK   EDEADLK  
    31.   
    32. #define EBFONT      59  /* Bad font file format */  
    33. #define ENOSTR      60  /* Device not a stream */  
    34. #define ENODATA     61  /* No data available */  
    35. #define ETIME       62  /* Timer expired */  
    36. #define ENOSR       63  /* Out of streams resources */  
    37. #define ENONET      64  /* Machine is not on the network */  
    38. #define ENOPKG      65  /* Package not installed */  
    39. #define EREMOTE     66  /* Object is remote */  
    40. #define ENOLINK     67  /* Link has been severed */  
    41. #define EADV        68  /* Advertise error */  
    42. #define ESRMNT      69  /* Srmount error */  
    43. #define ECOMM       70  /* Communication error on send */  
    44. #define EPROTO      71  /* Protocol error */  
    45. #define EMULTIHOP   72  /* Multihop attempted */  
    46. #define EDOTDOT     73  /* RFS specific error */  
    47. #define EBADMSG     74  /* Not a data message */  
    48. #define EOVERFLOW   75  /* Value too large for defined data type */  
    49. #define ENOTUNIQ    76  /* Name not unique on network */  
    50. #define EBADFD      77  /* File descriptor in bad state */  
    51. #define EREMCHG     78  /* Remote address changed */  
    52. #define ELIBACC     79  /* Can not access a needed shared library */  
    53. #define ELIBBAD     80  /* Accessing a corrupted shared library */  
    54. #define ELIBSCN     81  /* .lib section in a.out corrupted */  
    55. #define ELIBMAX     82  /* Attempting to link in too many shared libraries */  
    56. #define ELIBEXEC    83  /* Cannot exec a shared library directly */  
    57. #define EILSEQ      84  /* Illegal byte sequence */  
    58. #define ERESTART    85  /* Interrupted system call should be restarted */  
    59. #define ESTRPIPE    86  /* Streams pipe error */  
    60. #define EUSERS      87  /* Too many users */  
    61. #define ENOTSOCK    88  /* Socket operation on non-socket */  
    62. #define EDESTADDRREQ    89  /* Destination address required */  
    63. #define EMSGSIZE    90  /* Message too long */  
    64. #define EPROTOTYPE  91  /* Protocol wrong type for socket */  
    65. #define ENOPROTOOPT 92  /* Protocol not available */  
    66. #define EPROTONOSUPPORT 93  /* Protocol not supported */  
    67. #define ESOCKTNOSUPPORT 94  /* Socket type not supported */  
    68. #define EOPNOTSUPP  95  /* Operation not supported on transport endpoint */  
    69. #define EPFNOSUPPORT    96  /* Protocol family not supported */  
    70. #define EAFNOSUPPORT    97  /* Address family not supported by protocol */  
    71. #define EADDRINUSE  98  /* Address already in use */  
    72. #define EADDRNOTAVAIL   99  /* Cannot assign requested address */  
    73. #define ENETDOWN    100 /* Network is down */  
    74. #define ENETUNREACH 101 /* Network is unreachable */  
    75. #define ENETRESET   102 /* Network dropped connection because of reset */  
    76. #define ECONNABORTED    103 /* Software caused connection abort */  
    77. #define ECONNRESET  104 /* Connection reset by peer */  
    78. #define ENOBUFS     105 /* No buffer space available */  
    79. #define EISCONN     106 /* Transport endpoint is already connected */  
    80. #define ENOTCONN    107 /* Transport endpoint is not connected */  
    81. #define ESHUTDOWN   108 /* Cannot send after transport endpoint shutdown */  
    82. #define ETOOMANYREFS    109 /* Too many references: cannot splice */  
    83. #define ETIMEDOUT   110 /* Connection timed out */  
    84. #define ECONNREFUSED    111 /* Connection refused */  
    85. #define EHOSTDOWN   112 /* Host is down */  
    86. #define EHOSTUNREACH    113 /* No route to host */  
    87. #define EALREADY    114 /* Operation already in progress */  
    88. #define EINPROGRESS 115 /* Operation now in progress */  
    89. #define ESTALE      116 /* Stale NFS file handle */  
    90. #define EUCLEAN     117 /* Structure needs cleaning */  
    91. #define ENOTNAM     118 /* Not a XENIX named type file */  
    92. #define ENAVAIL     119 /* No XENIX semaphores available */  
    93. #define EISNAM      120 /* Is a named type file */  
    94. #define EREMOTEIO   121 /* Remote I/O error */  
    95. #define EDQUOT      122 /* Quota exceeded */  
    96.   
    97. #define ENOMEDIUM   123 /* No medium found */  
    98. #define EMEDIUMTYPE 124 /* Wrong medium type */  
    99. #define ECANCELED   125 /* Operation Canceled */  
    100. #define ENOKEY      126 /* Required key not available */  
    101. #define EKEYEXPIRED 127 /* Key has expired */  
    102. #define EKEYREVOKED 128 /* Key has been revoked */  
    103. #define EKEYREJECTED    129 /* Key was rejected by service */  
    104.   
    105. /* for robust mutexes */  
    106. #define EOWNERDEAD  130 /* Owner died */  
    107. #define ENOTRECOVERABLE 131 /* State not recoverable */  
    108.   
    109. #define ERFKILL     132 /* Operation not possible due to RF-kill */  
    110.   
    111. #endif  

    就是沒有找到139.

    A: 看來,系統(tǒng)已經(jīng)發(fā)生一些詭異的情況,錯誤碼已經(jīng)不正確了。為了確定139錯誤碼確實不存在,我們在/usr/include目錄下遞歸搜索139這個字符。

    1. grep -R '139' *  

    結(jié)果比較長,這里不列出來來。依然沒有能找到系統(tǒng)對應的139錯誤定義。

    那么,我們來看看系統(tǒng)日志吧,到底哪里可能有問題。


    Q: 使用如下命令得到了錯誤信息:

    最后的地方確實看到hello應用程序運行錯誤的系統(tǒng)日志。應該是指針訪問出錯。原因是否是匯編代碼大最后沒有恰當?shù)卦O置堆棧寄存器等寄存器的值呢?

    A: 在這里,很有可能。為了更容易看出問題可能在哪里,寫一個類似功能的c代碼,得到它的匯編代碼,和上面的匯編代碼進行比較。


    Q: 寫了如下的hello_1.c代碼如下:

    1. #include <stdio.h>  
    2.   
    3. int main()  
    4. {  
    5.     printf("Hello,world!\n");  
    6.     return 0;  
    7. }  
    查看它的匯編代碼:
    1.     .file   "hello_1.c"  
    2.     .section    .rodata  
    3. .LC0:  
    4.     .string "Hello,world!"  
    5.     .text  
    6. .globl main  
    7.     .type   main, @function  
    8. main:  
    9.     pushl   %ebp  
    10.     movl    %esp, %ebp  
    11.     andl    $-16, %esp  
    12.     subl    $16, %esp  
    13.     movl    $.LC0, (%esp)  
    14.     call    puts  
    15.     movl    $0, %eax  
    16.     leave  
    17.     ret  
    18.     .size   main, .-main  
    19.     .ident  "GCC: (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2"  
    20.     .section    .note.GNU-stack,"",@progbits  

    果然,和hello.s代碼確實有不一樣。這里,開始執(zhí)行時對ebp, esp進行了處理,最后使用了leave和ret命令。就是它們引起的嗎?

    A: 不過在實際中,不管是加入pushl  %ebp之類代碼,還是加入leave, ret指令,最終執(zhí)行依然是段錯誤。這個地方筆者一直沒明白,如果有誰知道的,希望能不吝賜教。不過,可以調(diào)用exit系統(tǒng)調(diào)用實現(xiàn)結(jié)束應用程序,這樣就不會出現(xiàn)段錯誤。如下:

    1. .section .rodata  
    2. str:  
    3. .ascii "Hello,world.\n"  
    4.   
    5. .section .text  
    6. .globl _main  
    7. _main:  
    8.   
    9. movl  $4,    %eax    # the number of system call   
    10. movl  $1,    %ebx    # file descriptor, 1 means stdout  
    11. movl  $str,  %ecx    # string address  
    12. movl  $13,   %edx    # string length  
    13. int   $0x80  
    14.   
    15. movl  $1,    %eax  
    16. movl  $0,    %ebx  
    17. int   $0x80  

    運行結(jié)果:


    Q: 進行0x80軟中斷進行系統(tǒng)調(diào)用,參數(shù)在哪里保存,就在上面寫的寄存器里面嗎?

    A: 是的。linux下,功能號和返回值在eax中保存,參數(shù)一般在5個以下,就按照ebx, ecx, edx, esi, edi來傳遞,如果參數(shù)過多,就會使用堆棧??梢钥吹缴厦鎯纱蜗到y(tǒng)調(diào)用,均是在使用ebx, ecx, edx這些寄存器。


    Q: 4號系統(tǒng)調(diào)用是什么?在哪里能知道?

    A: 可以在/usr/include/asm/unistd_32.h或者/usr/include/asm/unistd_64.h中看到平臺所有系統(tǒng)調(diào)用,下面為unistd_32.h文件中開始一部分:

    1. #define __NR_restart_syscall      0  
    2. #define __NR_exit         1  
    3. #define __NR_fork         2  
    4. #define __NR_read         3  
    5. #define __NR_write        4  
    6. #define __NR_open         5  
    7. #define __NR_close        6  
    8. #define __NR_waitpid          7  
    9. #define __NR_creat        8  
    10. #define __NR_link         9  
    11. #define __NR_unlink      10  
    12. #define __NR_execve      11  
    13. #define __NR_chdir       12  
    14. #define __NR_time        13  
    15. #define __NR_mknod       14  
    16. #define __NR_chmod       15  
    17. #define __NR_lchown      16  
    18. #define __NR_break       17  

    可以看到,1號系統(tǒng)調(diào)用為exit, 4號為write, 正是上面代碼使用的。


    Q: 匯編如何調(diào)用c庫函數(shù)?

    A: 使用call指令,不過調(diào)用前要傳好參數(shù)。如下代碼,調(diào)用c庫printf函數(shù):

    1. .section .rodata  
    2. str:  
    3. .ascii "Hello,world.\n"  
    4.   
    5. .section .text  
    6. .globl main  
    7. main:  
    8.   
    9. pushl   $str  
    10. call    printf  
    11.   
    12. pushl   $0  
    13. call    exit  

    保存為printf.s, 編譯:

    運行:


    Q: 可以使用as, ld來匯編以及鏈接嗎?

    A: 可以的。不過需要注意,因為它使用c庫,需要指定鏈接c庫:  -lc;


    Q:  乘法運算mul后面只跟著一個數(shù),另一個數(shù)存哪里?

    A: 另一個數(shù)存儲在al, ax或者eax寄存器中,這取決于使用的是mulb, mulw還是mull指令。結(jié)果將按照高位到地位的順序保存在dx和ax中。

    同理,除法運算div后面也只跟一個除數(shù),被除數(shù)保存在ax, dx:ax或者edx:eax中。除數(shù)的最大長度只能是被除數(shù)的一半。商和余數(shù)將根據(jù)被除數(shù)占用大小來確定:

    如果被除數(shù)在ax中,商在al, 余數(shù)在ah; 如果被除數(shù)在eax中,商在ax, 余數(shù)在dx; 如果被除數(shù)在edx:eax中,商在eax, 余數(shù)在edx.

    如下是測試代碼:

    1. #include <stdio.h>  
    2. #include <string.h>  
    3.   
    4. #define PRINT_D(longValue)       printf(#longValue" is %ld\n", ((long)longValue));  
    5. #define PRINT_STR(str)              printf(#str" is %s\n", (str));  
    6.   
    7.   
    8. static void assemble_func()  
    9. {  
    10.     int result_high, result_low;  
    11.     short result, remainder;  
    12.   
    13.    // mul  
    14.     __asm__("mov $10, %eax");  
    15.     __asm__("mov $10, %ebx");  
    16.     __asm__("mull %ebx");  
    17.     __asm__("mov %%edx, %0":"=r"(result_high));  
    18.     __asm__("mov %%eax, %0":"=r"(result_low));  
    19.     PRINT_D(result_high)  
    20.     PRINT_D(result_low)  
    21.   
    22.     // div  
    23.     __asm__("mov $0,   %dx");  
    24.     __asm__("mov $100, %ax");   // the divident is dx:ax  
    25.     __asm__("mov $9,  %bx");  
    26.     __asm__("div %bx");         // the divisor is bx  
    27.     __asm__("movw %%ax, %0":"=r"(result));  
    28.     __asm__("movw %%dx, %0":"=r"(remainder));  
    29.     PRINT_D(result)  
    30.     PRINT_D(remainder)  
    31. }  
    32.   
    33. int main()  
    34. {  
    35.     assemble_func();  
    36.     return 0;  
    37. }  

    輸出結(jié)果:

    1. result_high is 0  
    2. result_low is 100  
    3. result is 11  
    4. remainder is 1  


    Q:  對于數(shù)據(jù)比較指令cmp,它是如何配合jmp相關的指令?

    A:  cmp指令將進行兩個數(shù)據(jù)的差計算,如果得到的是0,jz成立; 如果不是0, jnz成立。如下例子:

    1. #include <stdio.h>  
    2. #include <string.h>  
    3.   
    4. #define PRINT_D(longValue)      printf(#longValue" is %ld\n", ((long)longValue));  
    5. #define PRINT_STR(str)          printf(#str" is %s\n", (str));  
    6. #define PRINT(str)              printf(#str"\n");  
    7.   
    8.   
    9. static void assemble_func()  
    10. {  
    11.     __asm__("mov $10, %eax");  
    12.     __asm__("cmp $10, %eax ");  
    13.     __asm__("jz  end");  
    14.     PRINT("below jz")  
    15.     __asm__("end:");  
    16.     PRINT("the end")  
    17.   
    18. }  
    19.   
    20. int main()  
    21. {  
    22.     assemble_func();  
    23.     return 0;  
    24. }  

    顯然,jz會成立,輸出如下:

    1. "the end"  

    Q: 對于某些時候,加法可能導致溢出,如何判斷出來?

    A: CPU內(nèi)部有一個寄存器,它內(nèi)部會保存溢出標志位OF, 可以通過jo或者jno判斷。

    1. #include <stdio.h>  
    2. #include <string.h>  
    3.   
    4. #define PRINT_D(longValue)      printf(#longValue" is %ld\n", ((long)longValue));  
    5. #define PRINT_STR(str)          printf(#str" is %s\n", (str));  
    6. #define PRINT(str)              printf(#str"\n");  
    7.   
    8.   
    9. static void assemble_func()  
    10. {  
    11.     __asm__("movw   $0x7FFF,  %ax");  
    12.     __asm__("movw   $0x7FFF,  %bx");  
    13.     __asm__("addw   %bx,      %ax");  
    14.   
    15.     __asm__("jo     overflow_set");  
    16.   
    17.     __asm__("movl   $1,       %eax");  
    18.     __asm__("movl   $0,       %ebx");  
    19.     __asm__("int    $0x80");  
    20.   
    21.     __asm__("overflow_set:");  
    22.     PRINT("overflow flag is set...")  
    23. }  
    24.   
    25. int main()  
    26. {  
    27.     assemble_func();  
    28.     return 0;  
    29. }  

    運行結(jié)果:

    1. "overflow flag is set..."  

    Q: 對于溢出,到底應該判斷?

    A: 以加法舉例,如果兩個相同符號的數(shù)相加得到的結(jié)果符號相反,那么一定溢出了。


    Q: OF和CF標志位有什么區(qū)別?

    A: CF代表進位標志。進位不一定是溢出,比如有符號整形最小值加1,雖然進位,但是沒溢出。因為計算機補碼的理論允許進位,但是結(jié)果卻正確。

    1. #include <stdio.h>  
    2. #include <string.h>  
    3.   
    4. #define PRINT_D(longValue)      printf(#longValue" is %ld\n", ((long)longValue));  
    5. #define PRINT_STR(str)          printf(#str" is %s\n", (str));  
    6. #define PRINT(str)              printf(#str"\n");  
    7.   
    8.   
    9. static void assemble_func()  
    10. {  
    11.     __asm__("movw   $0xFFFF,  %ax");  
    12.     __asm__("movw   $0x1,  %bx");  
    13.     __asm__("addw   %bx,      %ax");  
    14.   
    15.     __asm__("je     carry_set");  
    16.   
    17.     __asm__("movl   $1,       %eax");  
    18.     __asm__("movl   $0,       %ebx");  
    19.     __asm__("int    $0x80");  
    20.   
    21.     __asm__("carry_set:");  
    22.     PRINT("carry flag is set...")  
    23. }  
    24.   
    25. int main()  
    26. {  
    27.     assemble_func();  
    28.     return 0;  
    29. }  

    運行結(jié)果:

    1. "carry flag is set..."  

    當然,我們可以用jo來測試上面的加法是否溢出。

    1. #include <stdio.h>  
    2. #include <string.h>  
    3.   
    4. #define PRINT_D(longValue)      printf(#longValue" is %ld\n", ((long)longValue));  
    5. #define PRINT_STR(str)          printf(#str" is %s\n", (str));  
    6. #define PRINT(str)              printf(#str"\n");  
    7.   
    8.   
    9. static void assemble_func()  
    10. {  
    11.     __asm__("movw   $0xFFFF,  %ax");  
    12.     __asm__("movw   $0x1,  %bx");  
    13.     __asm__("addw   %bx,      %ax");  
    14.   
    15.     __asm__("jo     overflow_set");  
    16.   
    17.     __asm__("movl   $1,       %eax");  
    18.     __asm__("movl   $0,       %ebx");  
    19.     __asm__("int    $0x80");  
    20.   
    21.     __asm__("overflow_set:");  
    22.     PRINT("overflow flag is set...")  
    23. }  
    24.   
    25. int main()  
    26. {  
    27.     assemble_func();  
    28.     return 0;  
    29. }  

    執(zhí)行結(jié)果:


    它什么也沒輸出,這就意味著OF沒有被置位。


    作者:陳曦

    日期:2012-6-8 10:50:13

    環(huán)境:[Ubuntu 11.04  Intel-based x64 gcc4.5.2  CodeBlocks10.05  AT&T匯編  Intel匯編] 

    轉(zhuǎn)載請注明出處


      本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權內(nèi)容,請點擊一鍵舉報。
      轉(zhuǎn)藏 分享 獻花(0

      0條評論

      發(fā)表

      請遵守用戶 評論公約

      類似文章 更多

      主站蜘蛛池模板: 日韩精品一区二区亚洲AV| 久久久久亚洲精品无码蜜桃| 久久久久久久波多野结衣高潮| 亚洲精品国产电影| 91福利一区福利二区| 韩国午夜理伦三级在线观看仙踪林| 日韩内射美女人妻一区二区三区| 国产中文字幕在线精品| 亚洲欧洲精品专线| 2021亚洲国产精品无码| 亚洲国产精品人人做人人爱| 久久97精品久久久久久久不卡 | 国产精品IGAO视频网网址| 丁香五月亚洲综合在线国内自拍| 人妻精品久久无码专区精东影业| 国产成人无码免费视频在线| 国产精品亚洲А∨天堂免| 国产999精品2卡3卡4卡| 国产成人午夜福利在线观看| 国产精品中文字幕在线| 精品一区二区不卡无码AV| 亚洲av免费成人在线| 18精品久久久无码午夜福利 | 国产成人高清在线观看视频| 精品少妇人妻AV无码久久| 激情五月开心综合亚洲| 天天夜碰日日摸日日澡| 精品卡一卡二卡乱码高清| 我国产码在线观看av哈哈哈网站| 理论片午午伦夜理片久久| 精品中文人妻在线不卡| 日本不卡一区二区三区| 最新国产麻豆AⅤ精品无码| 好深好湿好硬顶到了好爽| 成人无码影片精品久久久| 亚洲国产精品久久久天堂麻豆宅男| 内射毛片内射国产夫妻| 少妇厨房愉情理9仑片视频| 中文字幕亚洲人妻系列| 无码国产69精品久久久久孕妇| 精品亚洲欧美无人区乱码|