注:
本文的所有代码是在我自己的VS2008中测试的,由于环境的差别,不能保证能在所有的编译器上运行。

1.内嵌汇编介绍

在C++中,可以通过__asm关键字来嵌入汇编语言。
例如

int main(){
__asm{//汇编!
mov eax,0
}
return 0;
}

2.汇编版本Hello, World!

我们知道,在C++中,可以使用printf函数来输出。(如果使用cout,需要使用运算符重载等技术,在这里反而不方便)

提示:
汇编中,调用函数的指令叫做CALL。
函数的参数是保存在栈中的。

那么我们可以开始写了。首先,先看看C++正常版本的:

#include<stdio.h>
#include<stdlib.h> const char *s1="Hello, World\n",*s2="pause";
int main(){
printf(s1);
system(s2); return 0;
}

为了方便,我们先把正常版本反汇编一下,结果是:

printf(s1);
00BD13CE mov esi,esp
00BD13D0 mov eax,dword ptr [s1 (0BD7038h)]
00BD13D5 push eax
00BD13D6 call dword ptr [__imp__printf (0BD82C4h)]
00BD13DC add esp,4
00BD13DF cmp esi,esp
00BD13E1 call @ILT+315(__RTC_CheckEsp) (0BD1140h)

第一句,mov esi,esp 为了后面检查栈是否正常用
第二句,mov eax,dword ptr[s1] 括号中的0BD7038h是地址,不要管他,意思是把地址放到eax中去
第三句,push eax 把刚才放进eax的地址放入栈, 实际就是把参数放入栈

第四句,call dword ptr [__imp__printf]
__imp__printf是printf函数编译后的结果,下划线开头表示这是一个函数
我们平时写内联汇编的时候直接写printf即可

第五句,add esp,4
其实是手动平栈,之前往栈里面放了4字节的s1,现在把esp指针也就是栈顶指针下移(栈从高地址往低地址),平栈

最后两句不管它,就是保证esi和esp相等,因为之前手动平了栈,结合第一句,这里应该是相等的,不写应该也没事

最终的内联汇编应该是这样:

#include<stdio.h>
#include<stdlib.h> const char *s1="Hello, World\n",*s2="pause";
int main(){
_asm{
mov eax,dword ptr [s1]
push eax
call dword ptr [printf]
add esp,4
mov eax,dword ptr[s2]
push eax
call dword ptr [system]
add esp,4
}
return 0;
}

运行结果正常。

3.内联汇编A+B

A+B问题,同时需要使用scanf和printf

首先注意一点,函数的参数在栈中是倒着存放的。(注:这个C标准没有规定,但是汇编语言本身就是非常依赖环境的一个东西,所以暂且不管它)

例如

scanf("%d %d",&a,&b);

如果翻译成汇编,应该是这样(下面的是伪代码)

push &b
push &a
push "%d %d"
call scanf

然后我们就可以开始写了。

scanf的部分,注意最前面两个参数,由于放入的是地址,所以不能使用MOV指令而是要使用LEA指令

lea eax,[a]

表示把a的地址放入eax中。

其他部分没有什么难度,注意最后平栈的时候,add esp到底加上多少,加上的是每个参数的大小相加。

例如scanf,每个都是4字节的地址,总共就是12字节。

完整代码

#include<stdio.h>
#include<stdlib.h> const char *s1="%d%d",*s2="%d\n",*s3="pause";
int a,b;
int main(){
_asm{
lea eax,[b]
push eax
lea eax,[a]
push eax
mov eax,dword ptr [s1]
push eax
call dword ptr [scanf]
add esp,12 mov eax,[a]
add eax,[b]
push eax
mov eax,dword ptr [s2]
push eax
call dword ptr [printf]
add esp,8 mov eax,dword ptr [s3]
push eax
call dword ptr [system]
add esp,4
}
return 0;
}

C++内嵌汇编 教程1的更多相关文章

  1. Beennan的内嵌汇编指导(译)Brennan's Guide to Inline Assembly

    注:写在前面,这是一篇翻译文章,本人的英文水平很有限,但内嵌汇编是学习操作系统不可少的知识,本人也常去查看这方面的内容,本文是在做mit的jos实验中的一篇关于内嵌汇编的介绍.关于常用的内嵌汇编(AT ...

  2. C内嵌汇编-格式

    C内嵌汇编-格式: __asm__(汇编语句部分:输出部分:输入部分破坏描述部分);C内嵌汇编以关键字"__asm__"或"asm"开始, 下辖四个部分, 各部 ...

  3. Linux内核--C语言中内嵌汇编 asm __volatile__

    在内嵌汇编中,可以将C语言表达式指定为汇编指令的操作数,而且不用去管如何将C语言表达式的值读入哪个寄存器,以及如何将计算结果写回C 变量,你只要告诉程序中C语言表达式与汇编指令操作数之间的对应关系即可 ...

  4. 转: __asm__ __volatile__内嵌汇编用法简述

    from: http://www.embedu.org/Column/Column28.htm __asm__ __volatile__内嵌汇编用法简述 作者:刘老师,华清远见嵌入式学院高级讲师,AR ...

  5. Linux内核系列—C语言中内嵌汇编 asm __volatile__,asm__volatile_【转】

    转自:http://www.bkjia.com/Androidjc/1109412.html 在内嵌汇编中,可以将C语言表达式指定为汇编指令的操作数,而且不用去管如何将C语言表达式的值读入哪个寄存器, ...

  6. ARM GCC 内嵌汇编手册

    转自:http://blogold.chinaunix.net/u2/69404/showart_1922655.html ARM GCC 内嵌(inline)汇编手册 关于这篇文档这篇文章是本人为方 ...

  7. arm汇编(c内嵌汇编及c和汇编互调)

    C语言编译成汇编: arm-linux-gcc -S test.c -o test.S C语言编译成可执行文件: arm-linux-gcc test.c -o test 多个文件编译链接: arm- ...

  8. 简单了解C语言内嵌汇编

    最近看自旋锁的实现,自选锁的循环查找锁的主要实现类似如下,该实现使用到了内嵌的汇编(摘自sanos内核,源代码有2处实现,一处使用intel汇编,是没有问题的,另一处使用内嵌汇编语法,源代码中为cmp ...

  9. C语言内嵌汇编(arm-v7)----加减乘移位

    在现代嵌入式操作系统中,汇编语言当然必不可少,汇编语言的优势就是执行速度快.如果在C语言的代码中,在关键的地方内嵌汇编,那么效率将会大大的提高,我们来看看代码: #include <stdio. ...

随机推荐

  1. 输入npm install 报错npm ERR! code ELIFECYCLE npm ERR! errno 1 npm ERR! node-sass@4.13.1 postinstall: `node scripts/build.js`

    输入npm install 报以下错误 npm ERR! code ELIFECYCLE npm ERR! errno 1 npm ERR! node-sass@4.13.1 postinstall: ...

  2. 【LeetCode】1181. Before and After Puzzle 解题报告(C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 保存首尾字符串 日期 题目地址:https://lee ...

  3. 【LeetCode】462. Minimum Moves to Equal Array Elements II 解题报告(Python & C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 方法一:排序 方法二:直接找中位数 日期 题目地址: ...

  4. LeetCode1240铺瓷砖

    题目 n*m的矩阵,只用正方形铺.求最少正方形个数. n,m<=13 思路 贪心: 加入是最大的正方形,显然行不通,比如n=11,m=13.那么贪心策略是1个11,其余是大小为2的正方形5个,大 ...

  5. Problem 2236 第十四个目标

    Problem 2236 第十四个目标 Accept: 4    Submit: 6Time Limit: 1000 mSec    Memory Limit : 32768 KB Problem D ...

  6. 1226 - One Unit Machine

    1226 - One Unit Machine   PDF (English) Statistics Forum Time Limit: 2 second(s) Memory Limit: 32 MB ...

  7. CS起源-havana地图红方打法分析

    作者:海底淤泥 havana是美国第一人称射击游戏<反恐精英>中的地图之一,编号为cs_havana,这张地图发生在古巴哈瓦那的某座城市中,恐怖分子们挟持了几名美裔的重要政治人物,以此为筹 ...

  8. c++定时器执行任务

    // // Created by leoxae on 19-9-2. // #ifndef KEEKOAIROBOT_TIMERTASKHELPER_H #define KEEKOAIROBOT_TI ...

  9. [opencv]白平衡算法中的灰度世界法,改善图像发红发蓝发绿的现象

    #include<iostream> #include <opencv2/opencv.hpp> #include <math.h> using namespace ...

  10. C#中ref关键字的用法总结

    ref表示引用的意思,C#中它有多种用法,这里简单总结一下: 1.按引用传递参数 具体可见:C#中的值传递与引用传递(in.out.ref) 2.引用局部变量 引用局部变量指的是在变量声明时使用ref ...