打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
汇编和c只有一步之近

作者:陈曦

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

环境:[Ubuntu 11.04  Intel-based x64 gcc4.5.2  CodeBlocks10.05  AT&T汇编  Intel汇编] 

转载请注明出处


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. }  

运行结果:
  1. temp is 3  

Q: assemble_func函数的汇编代码形式是什么?

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      

上面的汇编是在调试运行到assemble_func函数的开始时,使用disassemble命令得到的数据。注意第五行左侧的箭头符号是调试状态显示正在运行的行数。


Q: 上面的汇编是内嵌到c代码中的,单独完全的汇编代码,如何实现hello world的功能?

A: 从本质上说,只用汇编的形式需要对于底层更了解,c代码从编译的角度来说和汇编没什么区别,只是写的格式以及调用的东西看起来不一致罢了。

如下,是实现标准控制台输出功能的代码:

  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: 当然可以,不过这个文件显然不需要预处理了,它已经是汇编格式了,不需要单纯狭义的编译过程了,只需要从汇编过程开始了。

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


Q: 接下来做什么?可以直接执行它吗?

A: 试试。


此时,给hello.o添加可执行权限再执行:


Q: 这是为什么?

A: 继续观察hello.o文件的属性。

可以看出,它还不是可执行文件。其实很简单,hello.o只是目标文件,并没有链接成可执行文件。


Q: 这又是为什么?没有找到入口符号_start, ld默认的入口符号是_start?

A: 是的。在代码中使用的是_main, 所以应该让链接器明白,入口符号是_main.


Q: 现在应该可以运行了吧。运行一下:

Hello,world是输出了,为什么后面会出现段错误呢?

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

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


Q: 从系统的errno.h头文件以及相关文件中查找,得到所有系统错误码:

/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: 看来,系统已经发生一些诡异的情况,错误码已经不正确了。为了确定139错误码确实不存在,我们在/usr/include目录下递归搜索139这个字符。

  1. grep -R '139' *  

结果比较长,这里不列出来来。依然没有能找到系统对应的139错误定义。

那么,我们来看看系统日志吧,到底哪里可能有问题。


Q: 使用如下命令得到了错误信息:

最后的地方确实看到hello应用程序运行错误的系统日志。应该是指针访问出错。原因是否是汇编代码大最后没有恰当地设置堆栈寄存器等寄存器的值呢?

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代码确实有不一样。这里,开始执行时对ebp, esp进行了处理,最后使用了leave和ret命令。就是它们引起的吗?

A: 不过在实际中,不管是加入pushl  %ebp之类代码,还是加入leave, ret指令,最终执行依然是段错误。这个地方笔者一直没明白,如果有谁知道的,希望能不吝赐教。不过,可以调用exit系统调用实现结束应用程序,这样就不会出现段错误。如下:

  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  

运行结果:


Q: 进行0x80软中断进行系统调用,参数在哪里保存,就在上面写的寄存器里面吗?

A: 是的。linux下,功能号和返回值在eax中保存,参数一般在5个以下,就按照ebx, ecx, edx, esi, edi来传递,如果参数过多,就会使用堆栈。可以看到上面两次系统调用,均是在使用ebx, ecx, edx这些寄存器。


Q: 4号系统调用是什么?在哪里能知道?

A: 可以在/usr/include/asm/unistd_32.h或者/usr/include/asm/unistd_64.h中看到平台所有系统调用,下面为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号系统调用为exit, 4号为write, 正是上面代码使用的。


Q: 汇编如何调用c库函数?

A: 使用call指令,不过调用前要传好参数。如下代码,调用c库printf函数:

  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后面只跟着一个数,另一个数存哪里?

A: 另一个数存储在al, ax或者eax寄存器中,这取决于使用的是mulb, mulw还是mull指令。结果将按照高位到地位的顺序保存在dx和ax中。

同理,除法运算div后面也只跟一个除数,被除数保存在ax, dx:ax或者edx:eax中。除数的最大长度只能是被除数的一半。商和余数将根据被除数占用大小来确定:

如果被除数在ax中,商在al, 余数在ah; 如果被除数在eax中,商在ax, 余数在dx; 如果被除数在edx:eax中,商在eax, 余数在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. }  

输出结果:

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


Q:  对于数据比较指令cmp,它是如何配合jmp相关的指令?

A:  cmp指令将进行两个数据的差计算,如果得到的是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内部有一个寄存器,它内部会保存溢出标志位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. }  

运行结果:

  1. "overflow flag is set..."  

Q: 对于溢出,到底应该判断?

A: 以加法举例,如果两个相同符号的数相加得到的结果符号相反,那么一定溢出了。


Q: OF和CF标志位有什么区别?

A: CF代表进位标志。进位不一定是溢出,比如有符号整形最小值加1,虽然进位,但是没溢出。因为计算机补码的理论允许进位,但是结果却正确。

  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. }  

运行结果:

  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. }  

执行结果:


它什么也没输出,这就意味着OF没有被置位。


作者:陈曦

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

环境:[Ubuntu 11.04  Intel-based x64 gcc4.5.2  CodeBlocks10.05  AT&T汇编  Intel汇编] 

转载请注明出处


本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
在C\\C++中嵌入汇编
c语言内嵌汇编代码之Clobbers的用途到底是什么
程序中嵌入汇编的实例
glibc中fork系统调用传参
AT & T 汇编语法格式(与intel的不同)
C语言中的printf(" %d\n %d\n %d\n %d\n %d\n %d\n",++i,--i,i++,i--,-i++,-i--)
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服