C++内嵌汇编 教程1
注:
本文的所有代码是在我自己的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的更多相关文章
- Beennan的内嵌汇编指导(译)Brennan's Guide to Inline Assembly
注:写在前面,这是一篇翻译文章,本人的英文水平很有限,但内嵌汇编是学习操作系统不可少的知识,本人也常去查看这方面的内容,本文是在做mit的jos实验中的一篇关于内嵌汇编的介绍.关于常用的内嵌汇编(AT ...
- C内嵌汇编-格式
C内嵌汇编-格式: __asm__(汇编语句部分:输出部分:输入部分破坏描述部分);C内嵌汇编以关键字"__asm__"或"asm"开始, 下辖四个部分, 各部 ...
- Linux内核--C语言中内嵌汇编 asm __volatile__
在内嵌汇编中,可以将C语言表达式指定为汇编指令的操作数,而且不用去管如何将C语言表达式的值读入哪个寄存器,以及如何将计算结果写回C 变量,你只要告诉程序中C语言表达式与汇编指令操作数之间的对应关系即可 ...
- 转: __asm__ __volatile__内嵌汇编用法简述
from: http://www.embedu.org/Column/Column28.htm __asm__ __volatile__内嵌汇编用法简述 作者:刘老师,华清远见嵌入式学院高级讲师,AR ...
- Linux内核系列—C语言中内嵌汇编 asm __volatile__,asm__volatile_【转】
转自:http://www.bkjia.com/Androidjc/1109412.html 在内嵌汇编中,可以将C语言表达式指定为汇编指令的操作数,而且不用去管如何将C语言表达式的值读入哪个寄存器, ...
- ARM GCC 内嵌汇编手册
转自:http://blogold.chinaunix.net/u2/69404/showart_1922655.html ARM GCC 内嵌(inline)汇编手册 关于这篇文档这篇文章是本人为方 ...
- arm汇编(c内嵌汇编及c和汇编互调)
C语言编译成汇编: arm-linux-gcc -S test.c -o test.S C语言编译成可执行文件: arm-linux-gcc test.c -o test 多个文件编译链接: arm- ...
- 简单了解C语言内嵌汇编
最近看自旋锁的实现,自选锁的循环查找锁的主要实现类似如下,该实现使用到了内嵌的汇编(摘自sanos内核,源代码有2处实现,一处使用intel汇编,是没有问题的,另一处使用内嵌汇编语法,源代码中为cmp ...
- C语言内嵌汇编(arm-v7)----加减乘移位
在现代嵌入式操作系统中,汇编语言当然必不可少,汇编语言的优势就是执行速度快.如果在C语言的代码中,在关键的地方内嵌汇编,那么效率将会大大的提高,我们来看看代码: #include <stdio. ...
随机推荐
- java 数据类型:枚举类enum、对比方法compreTo()、获取名字.name()、获取对应值的枚举类Enum.valueOf()、包含构造方法和抽象方法的enum;实现接口;
问题引入 为了将某一数据类型的值限定在可选的合理范围内,比如季节只有四个:春夏秋冬. 什么是枚举类 Java5之后新增了enum关键字(他与class,interface关键字地位相同)用来定义枚举类 ...
- 『与善仁』Appium基础 — 26、常用手机操作的API说明
目录 1.获取当前手机的时间 2.获取手机屏幕的宽和高 3.获取手机当前网络 4.设置手机网络模式 5.操作手机通知栏 6.综合练习 7.发送键到设备(掌握) 8.手机截图(掌握) 是针对手机一些常用 ...
- C++之递归遍历数组
倒序输出 源码 void print_arr_desc(int arr[], unsigned int len) { if (len) { std::cout << "a[&qu ...
- cmake之引入外部项目(引用其他项目)、FetchContent管理子模块(fetchcontent用法)
本文CMAKE版本为3.18 演示环境: Windows+CMake+VS2017 源码下载说明 演示代码是后来传上去的,而且做了些修改,将spdlog_demo由exe改为了lib,但是,spdlo ...
- CMake之常用内置变量和message用法
关于 cmake 定义了相当丰富的变量,然而,我常用的也就那几个 脑子笨,记不住变量的值时,我会使用cmake的message函数输出变量值 为什么要写这个? 最近尝试使用Modern CMake, ...
- 【LeetCode】408. Valid Word Abbreviation 解题报告(C++)
作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 双指针 日期 题目地址:https://leetcod ...
- D. Persistent Bookcase(Codeforces Round #368 (Div. 2))
D. Persistent Bookcase time limit per test 2 seconds memory limit per test 512 megabytes input stand ...
- idea使用教程-常用快捷键
[1]创建内容:alt+insert [2]main方法:psvm [3]输出语句:sout [4]复制行:ctrl+d [5]删除行:ctrl+y [6]代码向上/下移动:Ctrl + Shift ...
- Redis -使用 Bitmap
redis数据类型 String.Set.Zset.List.hash Bitmap . 四种统计类型: 二值状态统计: 聚合统计: 排序统计: 基数统计 二值状态统计: 就是集合中的元素 ...
- 【项目管理】《IT项目管理》Kathy Schwalbe 第2章 IT项目管理和IT背景
1.对项目管理采取系统的观点有何意义?如何在项目管理中采用系统的观点? 意义:有效处理复杂的环境 采用系统方法,系统分析,系统管理.2.解释组织的四个框架.他们是如何帮助项目经理理解项目的组织环境的? ...