https://bpsend.net/thread-151-1-1.html

汇编使用资源

汇编使用资源的方式和C的一样,也是把资源文件 rc 编译成 res 再链接进去,汇编没有自己的资源编辑器,需要借助 vc6.0或者 vs

主要是把 头文件 .h 转化为对应的 .inc

使用vc6.0建立资源文件

用vs建立资源文件

  1. 新建一个桌面向导

生成文件之后,再打开 rc 文件,生成为

编译链接文件时要讲资源文件加进去

ml /c /coff %1.asm
if errorlevel 1 goto err
rc %1.rc ;如果用的是是vs自己生成的 res文件,就不需要
if errorlevel 1 goto err
link /subsystem:windows %1.obj %1.res
if errorlevel 1 goto err
OllyICE.exe %1.exe
:err
pause

汇编代码

.386
.model flat, stdcall
option casemap:none include windows.inc
include user32.inc
include kernel32.inc ;引入资源的头文件
include resource.inc includelib user32.lib
includelib kernel32.lib .data .code ;打开窗口的过程函数
DialogProc proc hwndDlg:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
.IF uMsg == WM_COMMAND
mov eax, wParam
.IF ax == BTN_TEST
;调用弹窗的函数
invoke MessageBox, NULL, NULL, NULL, MB_OK
.ENDIF
.ELSEIF uMsg == WM_CLOSE
invoke EndDialog, hwndDlg, 0
.ENDIF mov eax, FALSE ;返回结果
ret
DialogProc endp WinMain proc hInstance:HINSTANCE ;打开窗口函数 实例句柄必须给,不然找不到资源
invoke DialogBoxParam, hInstance, DLG_TEST, NULL, offset DialogProc, 0 ret
WinMain endp START:
invoke GetModuleHandle, NULL
invoke WinMain, eax
invoke ExitProcess, 0 end START

使用C库

动态库使用

可以看出,C库函数声明 在 msvcrt.inc中 并在前面加 crt_

.386
.model flat, stdcall
option casemap:none include windows.inc
include user32.inc
include kernel32.inc include msvcrt.inc ;c库头文件 includelib user32.lib
includelib kernel32.lib includelib msvcrt.lib ;c库实现文件 .data
g_szFmt db "%s %d %08X", 0dh, 0ah, 0
g_sz db "这是测试", 0 .code
main proc C invoke printf, offset g_szFmt, offset g_sz, 4096, 4096
;invoke strlen, offset g_sz ret
main endp START:
invoke main
invoke ExitProcess, 0
end START

静态库使用

.386
.model flat, stdcall
option casemap:none include windows.inc
include user32.inc
include kernel32.inc includelib user32.lib
includelib kernel32.lib includelib libc.lib ;C库的静态库 public main ;使用静态库必用要有 main函数 printf PROTO C :VARARG ; 函数声明 VARARG 变参类型
strlen PROTO C :DWORD ; 函数声明 .data
g_szFmt db "%s %d %08X", 0dh, 0ah, 0
g_sz db "这是测试", 0 .code
main proc C ;调用约定必须是c invoke strlen, offset g_sz ;调用c库函数 ret
main endp START:
invoke main ;调用main函数
invoke ExitProcess, 0
end START

汇编和C的互调

ml /c /coff test.asm

link /subsystem:console test.obj
link /subsystem:windows test.obj

使用obj文件

从语法上来将,c和汇编的语法是相互不兼容的,所以想在源码上进行相互间的调用是不可能的事情, 所以只能退而求其次 使用obj文件, 把 c 的 obj文件给汇编去用,把 汇编的 obj 文件 给 c 去用

c调用汇编的 obj文件
.386
.model flat, stdcall
option casemap:none include windows.inc
include user32.inc
include kernel32.inc includelib user32.lib
includelib kernel32.lib .data
g_szFmt db "%s %d %08X", 0dh, 0ah, 0
g_sz db "这是测试", 0 .code TestFunc PROC sz:dword
invoke MessageBox,NULL,sz,offset g_sz,MB_OK ;调用弹窗,显示传入的字符串
ret
TestFunc ENDP ;防止程序把 START 当做程序入口,直接退出程序
;START:
;invoke ExitProcess,0 ;退出程序
;end START end

查看 生成的obj 文件, 我们的 函数的名字

调用

  1. 新建一个 32位的桌面应用程序

  1. 把obj文件复制到工程目录下
  2. 再导入.bobj文件

  1. 去掉预编译头

extern "C" void __stdcall TestFunc(char* sz);   //对函数进行声明,注意调用约定

int main(int argc, char* argv[])
{ TestFunc("你好"); //调用汇编obj里面的函数 printf("Hello World!\n");
return 0;
}

用vs调用 汇编obj
.386
.model flat, stdcall
option casemap:none include windows.inc
include user32.inc
include kernel32.inc includelib user32.lib
includelib kernel32.lib Func proto c sz:DWORD ;将函数声明改成汇编形式 .data
g_szFmt db "%s %d %08X", 0dh, 0ah, 0
g_sz db "这是测试", 0 .code TestFunc PROC sz:dword
invoke MessageBox,NULL,sz,offset g_sz,MB_OK
ret
TestFunc ENDP end

把汇编生成的 obj 文件 放入项目

汇编使用C语言的 obj

1新建一个c的源文件

2取消预编译头

#include <windows.h>

void Func(char* sz)
{ MessageBox(NULL,sz,"这是c函数",MB_OK);
}

把 obj文件放到汇编代码同目录

.386
.model flat, stdcall
option casemap:none include windows.inc
include user32.inc
include kernel32.inc includelib user32.lib
includelib kernel32.lib Func proto c sz:DWORD ;将函数声明改成汇编形式 .data
g_szFmt db "%s %d %08X", 0dh, 0ah, 0
g_sz db "这是测试", 0 .code ;调用 c 的obj文件必须有,虽然没什么用
main proc c
ret
main endp TestFunc PROC sz:dword
invoke MessageBox,NULL,sz,offset g_sz,MB_OK
ret
TestFunc ENDP START:
invoke Func, offset g_sz
invoke ExitProcess,0 ;退出程序
end START

解决办法,把 vs 或者vc6的 lib 加入环境变量

汇编使用 vs 的 obj

在vs项目中添加一个 Func.c 文件 代码如下,生成解决方案

#include <windows.h>

void Func(char* sz)
{ MessageBox(NULL, sz, "这是c函数", MB_OK);
}

把obj文件放到同目录

.386
.model flat, stdcall
option casemap:none include windows.inc
include user32.inc
include kernel32.inc includelib user32.lib
includelib kernel32.lib Func proto c sz:DWORD ;将函数声明改成汇编形式 .data
g_szFmt db "%s %d %08X", 0dh, 0ah, 0
g_sz db "这是测试", 0 .code ;调用 c 的obj文件必须有,虽然没什么用
main proc c
ret
main endp TestFunc PROC sz:dword
invoke MessageBox,NULL,sz,offset g_sz,MB_OK
ret
TestFunc ENDP START:
invoke Func, offset g_sz
invoke ExitProcess,0 ;退出程序
end START

此时去编译链接项目 会有一大堆 外部符号找不到, 这些 库是vs 的 ,解决办法是把这些库加进来,或者使用 vs 的命令提示符.很麻烦,还要关掉一堆的检查,最好的方法使用dll

使用dll

dll的接口是很标准的,从dll出现为止,基本没变过

汇编使用 C 的 dll
  1. 用vs创建一个动态链接库

    // dllmain.cpp : 定义 DLL 应用程序的入口点。
    #include "pch.h" #include <windows.h> extern "C" void Func(char* sz) //声明函数和调用约定
    { MessageBoxA(NULL, sz, "这是c函数", MB_OK);
    } BOOL APIENTRY DllMain(HMODULE hModule,
    DWORD ul_reason_for_call,
    LPVOID lpReserved
    )
    {
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
    break;
    }
    return TRUE;
    }

    导出函数

    把生成 的 dll 和 lib 文件 放到汇编同目录下

    .386
    .model flat, stdcall
    option casemap:none include windows.inc
    include user32.inc
    include kernel32.inc includelib MyDll.lib ;导入lib库 includelib user32.lib
    includelib kernel32.lib Func proto c sz:DWORD ;将函数声明改成汇编形式 .data
    g_szFmt db "%s %d %08X", 0dh, 0ah, 0
    g_sz db "这是测试", 0 .code ;调用 c 的obj文件必须有,虽然没什么用
    main proc c
    ret
    main endp TestFunc PROC sz:dword
    invoke MessageBox,NULL,sz,offset g_sz,MB_OK
    ret
    TestFunc ENDP START:
    invoke Func, offset g_sz
    invoke ExitProcess,0 ;退出程序
    end START

    C使用汇编的DLL

    汇编也可以写成dll .注意字符集

    .386
    .model flat, stdcall
    option casemap:none include windows.inc
    include user32.inc
    include kernel32.inc includelib user32.lib
    includelib kernel32.lib .data
    g_sz db "这是测试", 0 .code
    TestFunc proc sz:DWORD
    invoke MessageBox, NULL, sz, offset g_sz, MB_OK
    ret
    TestFunc endp ; dll 必须要有 DllMain
    DllMain proc hinstDLL:HINSTANCE, fdwReason:DWORD, lpvReserved:LPVOID mov eax, TRUE
    ret
    DllMain endp end DllMain ;DllMain一般作为函数入口点

新建一个def 文件导出函数

此时dll中并没有导出函数,因为没有告诉链接器去用它

这个dll就可以给 c程序用了

把 生成 的 dll 和lib 放到正确位置

#include "framework.h"
#include "Project2.h" #pragma comment(lib, "asmdll.lib") 使用生成的 lib库
extern "C" void __stdcall TestFunc(char* sz); int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
TestFunc((char*)"你好");
}

内联汇编

内联

在c,c++中写汇编代码 ,在内联汇编中,宏汇编是无法使用的,但是部分伪指令是可以用的,而且只有 32位程序可以写,64位程序是无法内联汇编的

当我们想把某个函数注入到对方进程里面,这样就要求我们的代码是纯汇编的,因为一旦用到vs的代码,vs就会加一堆检查

格式: 关键字 __asm

 __asm         mov eax, eax
__asm mov eax, n
__asm {
mov eax, n0
mov n0, 10 push MB_OK
push sz
push NULL
push NULL
call MessageBoxA mov eax, size n
mov eax, length n
mov eax, offset wWinMain
}

// Project2.cpp : 定义应用程序的入口点。
// #include "framework.h"
#include "Project2.h"
#pragma comment(lib, "asmdll.lib")
extern "C" void __stdcall TestFunc(char* sz); void TestAsm(int n, char* sz)
{
int n0 = 9;
__asm {
mov eax, eax
mov eax, n
mov eax, n0
mov n0, 10 push MB_OK
push sz
push NULL
push NULL
call MessageBoxA //汇编里面调函数 ,宏汇编是无法使用的 //使用伪指令
mov eax, size n
mov eax, length n
mov eax, offset wWinMain
}
} //裸函数
__declspec(naked) void Test(int n, char* sz)
{
//裸函数申请栈空间
__asm
{
push ebp
mov ebp, esp
sub esp, 0x40
} ;裸函数不允许初始化变量
int n0;
float f0;
n0 = 9;
f0 = 3.14f;
if (n0 == n)
{
MessageBoxA(NULL, NULL, NULL, NULL);
} __asm
{
mov esp, ebp
pop ebp
ret
}
} int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
Test(99, (char*)"hello world");
TestAsm(99, (char*)"hello world");
//TestFunc((char*)"你好");
return 0;
}

裸函数 __declspec(naked)

正常一个空函数什么都不写.都回会有一些初数化操作,但是如果不要,可以声明 它是一个裸函数,就不会帮其生成代码,需要自己去生成

 
//裸函数 __declspec(naked) void Test(int n, char* sz) { __asm { push ebp mov ebp, esp sub esp, 0x40 } int n0; float f0; n0 = 9; f0 = 3.14f; if (n0 == n) { MessageBoxA(NULL, NULL, NULL, NULL); } __asm { mov esp, ebp pop ebp ret } } 

作业

Win32汇编学习笔记02.RadAsm和联合编译的更多相关文章

  1. 软件测试之loadrunner学习笔记-02集合点

    loadrunner学习笔记-02集合点 集合点函数可以帮助我们生成有效可控的并发操作.虽然在Controller中多用户负载的Vuser是一起开始运行脚本的,但是由于计算机的串行处理机制,脚本的运行 ...

  2. 汇编学习笔记(11)int指令和端口

    格式 int指令也是一种内中断指令,int指令的格式为int n,n是中断类型码.也就是说,使用int指令可以调用任意的中断例程,例如我们可以显示的调用0号中断例程,还记得在汇编学习笔记(10)中我们 ...

  3. Win32汇编学习(4):绘制文本

    这次,我们将学习如何在窗口的客户区"绘制"字符串.我们还将学习关于"设备环境"的概念. 理论: "绘制"字符串 Windows 中的文本是一 ...

  4. 机器学习实战(Machine Learning in Action)学习笔记————02.k-邻近算法(KNN)

    机器学习实战(Machine Learning in Action)学习笔记————02.k-邻近算法(KNN) 关键字:邻近算法(kNN: k Nearest Neighbors).python.源 ...

  5. OpenCV 学习笔记 02 使用opencv处理图像

    1 不同色彩空间的转换 opencv 中有数百种关于不同色彩空间的转换方法,但常用的有三种色彩空间:灰度.BRG.HSV(Hue-Saturation-Value) 灰度 - 灰度色彩空间是通过去除彩 ...

  6. SaToken学习笔记-02

    SaToken学习笔记-02 如果排版有问题,请点击:传送门 常用的登录有关的方法 - StpUtil.logout() 作用为:当前会话注销登录 调用此方法,其实做了哪些操作呢,我们来一起看一下源码 ...

  7. Redis:学习笔记-02

    Redis:学习笔记-02 该部分内容,参考了 bilibili 上讲解 Redis 中,观看数最多的课程 Redis最新超详细版教程通俗易懂,来自 UP主 遇见狂神说 4. 事物 Redis 事务本 ...

  8. 汇编学习笔记(3)[bx]和loop

    本文是<汇编语言>一书的学习笔记,对应书中的4-6章. 汇编程序的执行 要想将源代码变为可执行的程序需经过编译.连接两个步骤,WIN7操作系统下需要MASM程序来进行编译连接工作.将MAS ...

  9. Win32汇编学习(5):绘制文本2

    这次我们将学习有关文本的诸多属性如字体和颜色等. 理论: Windows 的颜色系统是用RGB值来表示的,R 代表红色,G 代表绿色,B 代表蓝色.如果您想指定一种颜色就必须给该颜色赋相关的 RGB ...

  10. OGG学习笔记02

    实验环境:源端:192.168.1.30,Oracle 10.2.0.5 单实例目标端:192.168.1.31,Oracle 10.2.0.5 单实例 1.模拟源数据库业务持续运行 2.配置OGG前 ...

随机推荐

  1. Python基础--python数据结构(字符串、列表和元组)

    前言 !!!注意:本系列所写的文章全部是学习笔记,来自于观看视频的笔记记录,防止丢失.观看的视频笔记来自于:哔哩哔哩武沛齐老师的视频:2022 Python的web开发(完整版) 入门全套教程,零基础 ...

  2. 解密注意力机制:为什么Flash Attention这么屌?

    背景回顾:什么是大语言模型(LLM)? 在进入注意力机制的细节之前,我们先了解一下什么是大语言模型(LLM).简单来说,LLM是一种通过深度学习技术训练的大规模神经网络模型,用于处理和生成自然语言.L ...

  3. 代码托管平台对比分析:Gitee与GitLab

    一.Gitee:本土化服务的深度实践者 Gitee凭借对中国开发者需求的精准洞察,提供了多项针对性优化功能,尤其适合国内团队: 高速稳定的访问体验 服务器均部署于国内,代码拉取.推送及CI/CD流程的 ...

  4. 【CF VP记录】Codeforces Round 1008 (Div. 2)

    比赛链接 本文原文发布于博客园,如您在其他平台刷到此文,请前往博客园获得更好的阅读体验. 跳转链接:https://www.cnblogs.com/TianTianChaoFangDe/p/18766 ...

  5. fs的proxy_media模式失效

    概述 freeswitch是一款简单好用的VOIP开源软交换平台. 在fs的使用过程中,某些场景只需要对rtp媒体做透传,又不需要任何处理. 在fs1.6的版本中,我们可以使用proxy_media来 ...

  6. idea 导入普通的项目后,无法发布

    之前一直都是在eclipse开发,现在改idea,但是很多隐藏的功能,都不晓得在哪里找到. 问题: 新导入一个spring 项目(没有maven),在界面上看是没有问题,但是使用tomcat部署项目的 ...

  7. MySQL常用SQL 语句

    --备份数据库 mysqldump -u用户名 -h主机名 -p密码 数据库名 > filename.sql --备份数据库中的某个表 mysqldump -u用户名 -h主机名 -p密码 数据 ...

  8. Java24你发任你发,我用Java8

    大家好,我是晓凡. 各位 Java 开发者们!是不是还在为 Java 23 的新特性忙得焦头烂额? 别急,Java 24 已经悄咪咪地发布了! 这可是自 Java 21 以来的第三个非长期支持版本,而 ...

  9. [每日算法 - 华为机试] 剑指 Offer 10- II. 青蛙跳台阶问题

    入口 力扣https://leetcode.cn/problems/qing-wa-tiao-tai-jie-wen-ti-lcof/ 题目描述 一只青蛙一次可以跳上1级台阶,也可以跳上2级台阶.求该 ...

  10. 冒泡排序--java进阶day06

    1.冒泡排序 https://kdocs.cn/l/ciMkwngvaWfz?linkname=150996835 我们会发现上图排序的样子非常像之前打印的倒三角,所以,冒泡排序也需要使用循环嵌套 2 ...