现在的位置: 首页 > 综合 > 正文

[利用asm代码学习c++语法]--hello world程序

2013年12月01日 ⁄ 综合 ⁄ 共 3193字 ⁄ 字号 评论关闭

在vs2005下建立vc++的win32 控制台应用程序,设置stdafx.h不必要包含,设置多字符集,设置汇编输出/FAs。编写代码如下:

#include <stdio.h>
int main(int argc, char* argv[])
{
 printf("hello world!/n");
 return 0;
}

对应的汇编输出为:

; Listing generated by Microsoft (R) Optimizing Compiler Version 14.00.50727.42

 TITLE e:/study/tc/t03/t03.cpp
 .686P
 .XMM
 include listing.inc
 .model flat

INCLUDELIB MSVCRTD
INCLUDELIB OLDNAMES

PUBLIC ??_C@_0O@OBPALAEI@hello?5world?$CB?6?$AA@ ; `string'
PUBLIC _main
EXTRN __imp__printf:PROC
EXTRN __RTC_CheckEsp:PROC
EXTRN __RTC_Shutdown:PROC
EXTRN __RTC_InitBase:PROC
; COMDAT ??_C@_0O@OBPALAEI@hello?5world?$CB?6?$AA@
; File e:/study/tc/t03/t03.cpp
CONST SEGMENT
??_C@_0O@OBPALAEI@hello?5world?$CB?6?$AA@ DB 'hello world!', 0aH, 00H ; `string'
CONST ENDS
; COMDAT rtc$TMZ
rtc$TMZ SEGMENT
__RTC_Shutdown.rtc$TMZ DD FLAT:__RTC_Shutdown
rtc$TMZ ENDS
; COMDAT rtc$IMZ
rtc$IMZ SEGMENT
__RTC_InitBase.rtc$IMZ DD FLAT:__RTC_InitBase
; Function compile flags: /Odtp /RTCsu /ZI
rtc$IMZ ENDS
; COMDAT _main
_TEXT SEGMENT
_argc$ = 8      ; size = 4
_argv$ = 12      ; size = 4
_main PROC      ; COMDAT

; 3    : {

 push ebp
 mov ebp, esp
 sub esp, 192    ; 000000c0H
 push ebx
 push esi
 push edi
 lea edi, DWORD PTR [ebp-192]
 mov ecx, 48     ; 00000030H
 mov eax, -858993460    ; ccccccccH
 rep stosd

; 4    :  printf("hello world!/n");

 mov esi, esp
 push OFFSET ??_C@_0O@OBPALAEI@hello?5world?$CB?6?$AA@
 call DWORD PTR __imp__printf
 add esp, 4
 cmp esi, esp
 call __RTC_CheckEsp

; 5    :  return 0;

 xor eax, eax

; 6    : }

 pop edi
 pop esi
 pop ebx
 add esp, 192    ; 000000c0H
 cmp ebp, esp
 call __RTC_CheckEsp
 mov esp, ebp
 pop ebp
 ret 0
_main ENDP
_TEXT ENDS
END
胡乱解释如下:

 .686P;指定使用的指令集
 .XMM;不清楚,XMM寄存器?新的指令集、寄存器相关。
 include listing.inc;包含头文件。
 .model flat;指定内存模式

;包含lib
INCLUDELIB MSVCRTD
INCLUDELIB OLDNAMES

;符号集,本程序只涉及6个符号
PUBLIC ??_C@_0O@OBPALAEI@hello?5world?$CB?6?$AA@ ; `string'
PUBLIC _main
EXTRN __imp__printf:PROC;外部函数名
EXTRN __RTC_CheckEsp:PROC
EXTRN __RTC_Shutdown:PROC
EXTRN __RTC_InitBase:PROC

CONST SEGMENT;const数据段定义
??_C@_0O@OBPALAEI@hello?5world?$CB?6?$AA@ DB 'hello world!', 0aH, 00H ; `string'
CONST ENDS

rtc$TMZ SEGMENT;外部函数段?
__RTC_Shutdown.rtc$TMZ DD FLAT:__RTC_Shutdown
rtc$TMZ ENDS
; COMDAT rtc$IMZ
rtc$IMZ SEGMENT
__RTC_InitBase.rtc$IMZ DD FLAT:__RTC_InitBase
; Function compile flags: /Odtp /RTCsu /ZI
rtc$IMZ ENDS

_TEXT SEGMENT;主要代码段?
_argc$ = 8      ; size = 4
_argv$ = 12      ; size = 4
_main PROC      ; COMDAT

; 3    : {                       ;      ";"号表示注释,此处对应代码第3行

 push ebp;EBP:Base Pointer进栈,保存main函数的上级调用函数的栈基地址
 mov ebp, esp;设置当前函数的栈基址
 sub esp, 192    ; 000000c0H
 push ebx
 push esi
 push edi
 lea edi, DWORD PTR [ebp-192];LEA - Load Effective Address
 mov ecx, 48     ; 00000030H
 mov eax, -858993460    ; ccccccccH
 rep stosd;STOS - Store String  (Byte, Word or Doubleword)

; 4    :  printf("hello world!/n");

 mov esi, esp
 push OFFSET ??_C@_0O@OBPALAEI@hello?5world?$CB?6?$AA@  ;string的地址进栈
 call DWORD PTR __imp__printf;函数调用
 add esp, 4;函数参数空间的回收
 cmp esi, esp;检查栈顶是否有误
 call __RTC_CheckEsp

; 5    :  return 0;

 xor eax, eax;XOR - Exclusive OR,eax寄存器是函数返回值保存的地方

; 6    : }

 pop edi;开始恢复调用_main函数之前的寄存器,并检查栈顶
 pop esi
 pop ebx
 add esp, 192    ; 000000c0H
 cmp ebp, esp
 call __RTC_CheckEsp
 mov esp, ebp
 pop ebp
 ret 0
_main ENDP
_TEXT ENDS

 

关于检查栈顶是否有误的代码如下:
_RTC_CheckEsp:
00412730 jne         esperror (412733h) ;不等就跳转到错误处理处
00412732 ret             
esperror:
……
00412744 call        _RTC_Failure (411195h)
……
00412754 ret 
; 5    :  return 1;但main函数结尾处return 1时xor eax, eax变成如下代码
 mov eax, 1

抱歉!评论已关闭.