本文介绍利用RedASM写一个messageBox “hello world”.
.386
.model flat, stdcall
option casemap :none
include windows.inc
include kernel32.inc
include masm32.inc
includelib kernel32.lib
includelib masm32.lib
.data
helloWorld db "hello world",0
.code
start:
invoke StdOut, addr helloWorld
invoke ExitProcess,0
end start
2.习题:有1、2、3、4个数字,能组成多少个互不相同且无重复数字的三位数?都是多少?
写成c代码很简单:
void p1_fun() { for ( int i = 1; i <= 4; ++i){ for ( int j = 1; j <= 4; ++j){ for ( int k = 1; k <=4; ++k){ if (i !=j && i !=k && j != k){ ostringstream stringStream; stringStream<<i<<j<<k; cout<<stringStream.str()<< "," ; } } } } } |
用汇编实现如下
Title: Hello world ;Author: sld6666666@gmail.com ;Data: 2012-11-29 ;Description: Assemble hello world .386 ;¸Ã³ÌÐò¶ÔCPUµÄ×îµÍÒªÇóÊÇintel 386 .model flat, stdcall ; ƽ̹ÄÚ´æÄ£ÐÍ£¬ stacll º¯Êýµ÷Ó÷½Ê½ .stack 4096 ;Õ»µÄ´óСΪ4096B option casemap:none ;include Í·Îļþ£¬ Á¬½Ó¿â include msvcrt.inc includelib msvcrt.lib .data ;Êý¾Ý¶Î index_0 dd dword index_1 dd dword index_2 dd dword szFmt db '%d%d%d' , 0 entryFmt db ' ' ,0 .code start: mov index_0, 0 forProcess_0: cmp index_0, 5 jge rtnProcess inc index_0 mov index_1, 0 forProcess_1: cmp index_1, 5 jge forProcess_0 inc index_1 mov index_2, 0 forProcess_2: cmp index_2, 5 jge forProcess_1 inc index_2 mov eax, index_0 mov ebx, index_1 mov edx, index_2 cmp eax, ebx je forProcess_2 cmp eax, edx je forProcess_2 cmp ebx, edx je forProcess_2 invoke crt_printf, addr szFmt,eax, ebx, edx invoke crt_printf, addr entryFmt jmp forProcess_2 rtnProcess: ret end start |
解释下几个关键点:
1. 输出函数利用了 msvcrt 中的printf
2. 导入库的关键字为includelib, 头文件的关键字为 include, 如include msvcrt.inc,includelib msvcrt.lib
3. 使用导入函数的关键字为 invoke
3习题: 输入某年某月某日,判断这一天是这一年的第几天?
c++代码如下, 算法不太严谨,主要为了反汇编的练习也不讲究了
void doFun( int year, int month, int day){ int days = month*30+day; days += month/2 + month%2; //31天的月 if (month >= 2){ days -= (year%4==0)?1:2; } cout << days <<endl; } |
相应的汇编代码为:
Title: Hello world ;Author: sld6666666@gmail.com ;Data: 2012-11-29 ;Description: Assemble hello world .386 .model flat, stdcall .stack 4096 option casemap:none include msvcrt.inc includelib msvcrt.lib .data year dword 2009 month dword 5 day dword 24 totalDays dword 0 szFmt db '%d' , 0 .code start: ; int days = month*30+day; mov eax, 30 mul month add eax, day mov totalDays, eax ;days += month/2 + month%2; //31ÌìµÄÔ mov eax, month cdq mov ebx, 2 idiv ebx add totalDays, ebx add totalDays, edx ; if (month >= 2){ ; days -= (year%4==0)?1:2; ;} mov eax, month cmp eax, 2 jb printProcess mov eax, year cdq mov ebx, 4 idiv ebx cmp edx, 0 je L1 sub totalDays, 2 jmp printProcess L1: sub totalDays, 1 printProcess: invoke crt_printf, addr szFmt,totalDays rtnProcess: ret end start |
题目:输入三个整数x,y,z,请把这三个数由小到大输出
c++ 代码很简单
void doFunP3( int x, int y, int z){ if (x > y)swap(x, y); if (x > z)swap(x, z); if (y > z) swap(y, z); cout<< x << ',' << y << ',' << z <<endl; } |
汇编的代码如下
![](https://img-blog.csdnimg.cn/img_convert/a904f66ef5e68396d2a6726ff2db610a.gif)
.data ;Êý¾Ý¶Î
x dword 200
y dword 10
z dword 400
printFmt db '%d,%d,%d', 0
.code
sortEaxEbx proc
cmp eax, ebx
jbe rtnProcess
swapProcess:
xchg eax, ebx
rtnProcess:
ret
sortEaxEbx endp
print proc
mov eax, x
mov ebx, y
invoke sortEaxEbx
mov x, eax
mov y, ebx
mov eax, x
mov ebx, z
invoke sortEaxEbx
mov x, eax
mov z, ebx
mov eax, y
mov ebx, z
invoke sortEaxEbx
mov y, eax
mov z, ebx
invoke crt_printf, addr printFmt, x, y, z
ret
print endp
![](https://img-blog.csdnimg.cn/img_convert/c79b3b982d06d915ec4f6d7aa1722e78.gif)
这里说下几个注意的点:
1. invoke 伪指令等同于call指令,但是比call 更强大
2. 如果要在不同的文件中实现模块功能, 一定要遵循如下:
a)建立一个头文件,如: p3.inc, 并在此头文件中声明函数: print PROTO
b) 在相应的实现文件中实现功能代码, p3.asm:
c): 作为调用者main.cpp 必须包含头文件和实现文件
include p3.inc
include p3.asm
d). 如果 功能函数不被导出, 则不必在头文件中声明
e):不管是什么样的实现函数必须放在.code中