汇编2.汇编版本的helloworld
寻址方式
立即数寻址
寄存器寻址
存储器寻址
直接寻址 :
mov ax, [ 01000h ];直接在[]内给出一个内存地址寄存器间接寻址:
mov ax ,[si]; 在[]以寄存器的值给出内存地址.寄存器相对寻址:
mov ax,[si+0ch]在[]以寄存器的值和一个数相加之后作为内存地址.struct MyStruct{
int n1;
char ch;
int n2;
};
MyStruct stc;
stc.n1 = 0;
stc.n2 = 10;
//假设stc的内存首地址是0x1000
// 以汇编形式访问结构体字段:
mov bx , 0x1000; // bx保存了结构体首地址
mov [bx+0] , 0; //stc.n1
mov [bx+8] , 10;//stc.n2基址变址寻址:
mov ax,[si+bx]使用两个寄存器相加之和作为内存地址char szBuff[10];
for(int i = 0; i<10;++i){
szBuff[i] = 0;
}
// 假设szBuff首地址是0x1000
mov si , 0x1000;
xor bx,bx;
for(int i =0;i<10;++i){
// szBuff[i] = 0;
mov [si+bx] , 0;
inc bx;
}相对基址变址寻址:
mov ax,[si+bx+0ch]使用[]内的表达式的相加之和作为内存地址.在16位汇编中, 要使用存储器寻址的时候, 如果希望用寄存器寻址, 那么只能使用
si,di,bx,bp寄存器, 然后这些寄存器不能任意组合.
条件跳转指令
有有符号跳转和无符号跳转之分.
常见条件跳转指令:
有符号跳转:
jg大于jge大于等于jl小于jle小于等于
无符号跳转
ja大于, cf0 且 zf0则跳转jae大于等于 , cf ==0 则跳转jb小于, cf==1则跳转jbe小于等于, cf1 或 zf1则跳转
不区分符号跳转
jezf==1 则跳转jnezf==0 则跳转
32位汇编
第一个汇编项目
.386 ;告诉汇编器, 使用32位汇编的语法来编译
.model flat , stdcall ;默认使用平坦模式,默认使用stdcall的调用约定
option casemap:none
.code ; 定义一个代码段
sldkfjlaskdjfmain:
ret
end sldkfjlaskdjfmain; 指定程序入口点
end ; 结束代码段
masm汇编器的语法
每个asm源码文件中都以下面的指令打头:
.386 ;告诉汇编器, 使用32位汇编的语法来编译
.model flat , stdcall ;默认使用平坦模式,默认使用stdcall的调用约定
option casemap:none必须自己定义一个代码段, 定义代码段使用
.code伪指令 , 汇编指令就写在.code和end之间程序必须要有一个入口点.在C语言中, 就固定了是
main函数. 在masm里面, 可以在代码段中使用end 标签的方式来指定入口点.数据的定义必须放在数据段, 数据段使用
.data指令来定义..data ; 定义数据段
.const ; 定义常量数据(不可修改的数据)
.code ; 定义代码段在数据段中定义数据, 可以使用
d系列指令.data
ch db 'a' ; 相当于 char ch='a';
buff db 0,0,0,0 ; 相当于 char buff[]={0,0,0,0};
str db "hello" , 0; 相当于 char str[]={'h','e','l','l','o' , 0 }; 也就是说,这里不会自动加上字符串结束符'\0'
str2 db "hello\n" , 0; 在masm中没有转义字符.
str2 db "hello", 0ah , 0 ; 0ah是'\n'
; 其它类型
var1 dw 100 ; word类型
var2 dd 100 ; dword类型
; dup用于重复定义数据 , dup前是一个重复的次数, dup圆括号内是需要重复的初始化值.
arr dd 100 dup(0) ; int arr[100]={0};
汇编版本的helloworld
.386 ;告诉汇编器, 使用32位汇编的语法来编译
.model flat , stdcall ;默认使用平坦模式,默认使用stdcall的调用约定
option casemap:none ; 不区分大小写
; 包含名为`msvcrt.inc`头文件(c语言的所有库函数)
include msvcrt.inc
; 包含库文件
includelib msvcrt.lib
;include windows.inc
;include user32.inc
;includelib user32.lib
.data
g_str db "hello world",0dh,0ah, 0 ; \r\n==0d0a
.code ; 定义一个代码段
main:
push offset g_str;
call crt_printf
add esp , 4
ret
end main; 说明程序入口点
end ; 结束代码段
汇编程序基础
三大程序结构
顺序结构
选择结构
在c中,
if else,switch
循环结构
模拟选择结构
模拟if-else
int n =0;
scanf("%d",&n);
if( n == 1){
printf("星期一\n");
}
else if(n==2){
printf("星期二\n");
}
else if(n==3){
printf("星期三\n");
}
汇编版本
.data
n dd 0 ; 定义一个全局变量, 名字为n
.code
_main:
cmp n , 1
je _FLAG1
cmp n , 2
je _FLAG2
cmp n , 3
je _FLAG3
_FLAG1:
printf("星期一\n");
jmp _ENDIF
_FLAG2:
printf("星期二\n");
jmp _ENDIF
_FLAG3:
printf("星期三\n");
_ENDIF:
end _main
end
模拟switch-case
switch( n )
{
case 1: printf("星期1\n");break;
case 2: printf("星期2\n");break;
case 3: printf("星期3\n");break;
}
汇编版本1(和if-else的一样)
汇编版本1 : 使用跳转表
.386 ;告诉汇编器, 使用32位汇编的语法来编译
.model flat , stdcall ;默认使用平坦模式,默认使用stdcall的调用约定
option casemap:none ; 不区分大小写 ; 包含名为`msvcrt.inc`头文件(c语言的所有库函数)
include msvcrt.inc
; 包含库文件
includelib msvcrt.lib ;include windows.inc
;include user32.inc
;includelib user32.lib .data
g_str db "hello world",0dh,0ah, 0 ; \r\n==0d0a
str1 db "星期一",0dh,0ah,0
str2 db "星期2",0dh,0ah,0
str3 db "星期3",0dh,0ah,0 .code ; 定义一个代码段 main:
.code
jmp being
jmptable dd _FLAG1,_FLAG2,_FLAG3 ; 在code段定义数据
being:
mov eax , 1 ; ;
dec eax;
jmp [jmptable+eax*4]; 根据eax的值,来跳转不同的位置. _FLAG1:
invoke crt_printf, offset str1;
jmp _ENDIF
_FLAG2:
invoke crt_printf , offset str2;
jmp _ENDIF
_FLAG3:
invoke crt_printf ,offset str1;
_ENDIF: end main; 说明程序入口点
end ; 结束代码段
模拟循环结构
使用条件跳转模拟循环
int i =0;
while (i < 10)
{
++i;
}
汇编版本1:
xor eax,eax ; 使用eax寄存器作为i
_WHILE:
cmp eax , 10 ;
jge _ENDWHILE
inc eax
jmp _WHILE
_ENDWHILE:
汇编版本2 : loop 循环, 该指令使用ecx作为默认寄存器, 保存着循环次数, loop指令执行之后, 会判断ecx的值是否等于0 , 如果等于了,就不会跳转, 如果没有等于, 就先将ecx递减1, 然后跳转
mov ecx , 10;
_WHILE: loop _WHILE ;
函数结构
函数调用和函数返回语句
call,retcall 目标地址- 调用函数的指令会将call指令的下一条指令的地址push到栈中.
跳转到目标地址.
ret返回指令其实就是
pop eip,call指令将一个返回地址保存到栈中,ret就默认把栈中的地址取出设置到eip这样就能回调函数的调用点了.ret 字节数- 返回时,顺便平衡指定字节栈空间.
定义函数
通过
ret指令来回到函数的调用点.
调用函数
函数的传参是通过栈来完成的.
调用函数之前, 先将实参压入栈中.
进入函数之后, 就可以从栈中取出参数了.
在传参的时候, 是从右往左依次将参数入栈,还是从左往右,需要有一个函数调用约定
调用约定名 传参顺序 栈平衡者 _cdecl- C调用约定从右往左 函数外部 _stdcall- 标准调用约定从右往左 函数内部 _thiscall- 对象调用从右往左,this指针保存到ecx寄存器 函数内部 fastcall- 快速调用约定前两个参数通过 ecx,edx来传递, 后面的参数从右往左依次入栈传递函数内部
通过
call + 函数地址完成调用
在函数内部定位栈中的参数
汇编2.汇编版本的helloworld的更多相关文章
- EJB2.0版本的HelloWorld
EJB2.0版本的HelloWorld 虽然EJB3.1已经出来了,可是EJB2.0的项目还需要维护啊.下面写个简单EJB2.0的HelloWorld程序,练练手. 环境: JBoss 4.0 ...
- iOS汇编系列-汇编入门
概述 汇编语言(Assembly Language)用符号代替了0和1,比机器语言更便于阅读和记忆. 但是同样汇编语言同样指令太多不便于记忆,就出现了高级语言.C\C++\Java\Swift等,更接 ...
- JDK-windows7环境变量配置-亲测版本 以及HelloWorld
1.下载并安装jdk,假设安装1.6.0_45版本到C:\Program Files\Java,则安装完毕后,目录结构为: C:\PROGRAM FILES\JAVA├─jdk1.6.0_45│ ├─ ...
- ARM汇编初探---汇编代码中都有哪几类指令---ARM伪指令介绍
要学习一个东西首先要把概念搞清楚,以下仅仅是自己的一些关于汇编的理解. 可运行文件里的01码是机器码,机器码不等于汇编码,尽管机器码能够非常easy翻译成汇编码. 汇编码中包括非常多汇编指令.伪指令和 ...
- 汇编 | x86汇编指令集大全(带注释)
做mit-6.828的时候遇到了很多汇编知识,但是无奈学校还没学汇编,只能狠心啃啃硬骨头,在网上查到了很多的资料,归档!方便查看 ----------------------------------- ...
- 第二个hibernate Annotation版本的helloworld
经过第一次的 hibernate 我发现每一个数据库表都对应了一个类,并且每一个类都要新建一个文件进行配置 很麻烦! 于是便出现了Annotation版本的hibernate. 具体如下: 1.同 ...
- Hibernate学习笔记1.2(Annotation版本的Helloworld)
hibernate 3.0之后开始支持Annotation 接着1.1的项目 首先 需要创建model Teacher.java. package com.hw.hibernate.model; pu ...
- Go语言版本的helloworld
新建一个project,然后建立一个main目录,在main目录下新建一个go类文件:main.go 内容如下: package main import "fmt" func ma ...
- Annotation版本的HelloWorld
hiberante 的 annotation历史: 在hibernate3以后,开始支持Annotation; 先有hiberante再有JPA,有了JPA标准之后,hibernate写了Annota ...
随机推荐
- Top的VIRT是什么
Top命令监控某个进程的资源占有情况 下面是各种内存: VIRT:virtual memory usage 1.进程“需要的”虚拟内存大小,包括进程使用的库.代码.数据等 2.假如进程申请1 ...
- python学习笔记3-循环1
1 while break continue #while语句 ''' while 判断条件: 执行语句…… ''' count = 0 while (count < 9): print ('T ...
- mysql数据库基本操作(五)
表纪录之查(单表查询)2 上一篇讲了4类查询的方式,现在接着上一篇继续看还有哪些方式. group by 分组查询 顾名思义,分组查询要分组,因为mysql5.7之后默认不支持group by语句,需 ...
- [置顶] 一位ACMer过来人的心得
刻苦的训练我打算最后稍微提一下.主要说后者:什么是有效地训练? 我想说下我的理解. 很多ACMer入门的时候,都被告知:要多做题,做个500多道就变牛了.其实,这既不是充分条件.也不会是 ...
- 51Nod 1013 3的幂的和(快速幂+逆元)
#include <iostream> #include <algorithm> #include <string> #define MOD 1000000007 ...
- Centos6.8 搭建 Mysql 主从复制
实例环境: MySQL-Master:Centos-6.8:192.168.153.130 MySQL-Slave:Centos-6.8:192.168.153.131 1.两台服务器安装mysql ...
- Python实现两已知排好序的列表合并成一个排好序的列表
#方法0.5--- lst1 = [1, 3, 7, 9, 12] lst2 = [4, 8, 9, 13, 15, 19] def merge(a, b): c = [] h = j = 0 whi ...
- [NOIP2018校模拟赛]T2矩阵分组 Matrix
题目链接: 矩阵分组 分析: 这道题求的是两部分极差当中大的那个的最小值.对于这种求最值的问题,我们很自然(其实并没有)地想到二分答案. 这个题有两个结论: (好像当时看出来了第一个?然后发现下面都不 ...
- 二分搜索 2015百度之星初赛1 HDOJ 5248 序列变换
题目传送门 /* 二分搜索:在0-1e6的范围找到最小的max (ai - bi),也就是使得p + 1 <= a[i] + c or a[i] - c 比赛时以为是贪心,榨干智商也想不出来:( ...
- 根据 目录号 案卷号 用户名 查询 page 中 的条数
select count(*) from am_b_page a join am_b_entry b on a.entry_id=b.entry_id where b.catalogue_code=' ...