使用YASM编程

来源:互联网 发布:图片放大器 js 编辑:程序博客网 时间:2024/06/10 14:45

YASM 继承了NASM ,扩展了支持的语法和平台
支持INTEL 格式语法和 GNU AS 语法
下面是一个例子,实现了简单的invoke 调用和编程的一个基本的框架
它能够:
0 win32 程序,控制台打印
1 调用外部程序
2 被外部调用(入口函数)
3 数据段
4 代码段
5 函数定义
6 函数从栈传入参数,从eax返回值
7 include 其他的文件
8 编译
9 链接

;;;;;;;;;;;;;;;;;;;;;;;;;windows.inc;;;;;;;;;;;;;;;;;;;;;;;;%ifndef windows_inc%define windows_inc 1extern _CreateFileA@28extern _CreateFileW@28extern _MessageBoxA@16extern _MessageBoxW@16extern _OutputDebugStringA@4extern _OutputDebugStringW@4extern _ExitProcess@4;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;帮助我们像使用C语言一样使用API;定义很多宏供用户使用%define CreateFileA _CreateFileA@28%define CreateFileW _CreateFileW@28%define MessageBoxA _MessageBoxA@16%define MessageBoxW _MessageBoxW@16%define OutputDebugStringA _OutputDebugStringA@4%define OutputDebugStringW _OutputDebugStringW@4%define ExitProcess _ExitProcess@4;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;%endif;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;test.asm;这个是 YASM 的样板程序,使用一下NASM的各个语法使以后变成可以参考这个程序;大体一个程序使用一下的功能; 入口:必须以 _ 开始,因为在link 的时候 link /entry:xxxx ,这个xxxx 是C的符号xxxx,;       真实的是_xxxx; 数据段:;   section .data  ; 在masm中是  .data 没有section修饰; 代码段:;   section .text  ; 在masm中是  .code; 导出的符号:;   global xxxx;   必须要导出入口,否则链接程序找不到这个入口函数; 引入的符号:;   extern xxxx;   说明这个符号是外部的,在此不存在,只是一个占位符,在其他模块应该能够找到它; 伪操作符;    db;   dw;   equ; 宏定义;   %define xxxx yyyyyy ; 和 C的宏样子类似; 调用约定:;   这里没有调用约定,所以导入的符号的名称都比较原始;   比如:MessageBoxA 这个函数,在dll内部其实是_MessageBoxA@16(因为它有4个函数所以叫16);   调用的时候 stdcall 不需要处理栈平衡,因此在我们call了之后什么都没有处理;   调用C函数的时候如何处理呢?;    push hello;    call _printf;    add esp,4;    只能这样手动的维持栈平衡;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;test.asm;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;编译和链接;vsyasm -f win32 -o obj test.asm;link /entry:start /subsystem:console /debug /machine:x86 /out:test.exe /release /verbose:lib ;     /libpath:"C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Lib"  ;     kernel32.lib user32.lib test.obj msvcrt.lib;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;数据段,不可变;SECTION .data 都可以%include "windows.inc"SECTION .data    HelloMsg: db "Hello",0    TitleString db "msg",0    Hello : db "Hello Yasm",0x0a,0    printFormat : db "retValue=%d",0x0a,0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;includelib---------------------------extern _printf;-------------------------------------;压栈;%macro push_param 1-* ;*表示宏的参数个数没有上限;    %rep %0        ;参数旋转,最后一个参数为1;        %rotate -1        ;将 %1 参数入栈;        push %1;    %endrep;%endmacro;;;;;;;;;;;;;;;;;;;;;;;;;;;;macro invoke;使用宏来实现MASM 中的invoke;当参数最高达到2的时候,后续的;参数全部编程%2;invoke 只能调用参数个数>1的函数;参数个数=0的函数请使用 call 来调用;;;;;;;;;;;;;;;;;;;;;;;;;;;;%macro invoke 2-*    %define _j %1    %rep %0-1        %rotate -1        push dword %1    %endrep    call _j%endmacro;%macro invoke 2+ ;     ;循环%0 表示宏的参数个数;    push_param %2;    call %1;%endmacro;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;SECTION .textglobal _startprintRetValue:    push ebp    mov ebp,esp    mov eax,[ebp+8]    invoke _printf,printFormat,eax    add esp,8    pop ebp    retadd1:    push ebp    mov ebp,esp    mov eax,[ebp+8]    mov edx,[esp+0ch]    add eax,edx    pop ebp    retsayHello:    mov eax,Hello    push eax    call _printf    add esp,4    ret_start:    invoke add1,100,200    invoke printRetValue,eax    call sayHello           invoke MessageBoxA,0,HelloMsg,TitleString,0    push HelloMsg    call OutputDebugStringA    invoke ExitProcess,0    ret