学了win32的汇编再去学linux汇编会很容易上手么,学 Win32 汇编[17]: 关于压栈(PUSH)与出栈(POP) 之一...

记得刚学多线程的时候, 碰到一个结构:

//Delphi 的语法描述

PContext = ^TContext;

_CONTEXT = record

ContextFlags: DWORD;

Dr0: DWORD;

Dr1: DWORD;

Dr2: DWORD;

Dr3: DWORD;

Dr6: DWORD;

Dr7: DWORD;

FloatSave: TFloatingSaveArea;

SegGs: DWORD;

SegFs: DWORD;

SegEs: DWORD;

SegDs: DWORD;

Edi: DWORD;

Esi: DWORD;

Ebx: DWORD;

Edx: DWORD;

Ecx: DWORD;

Eax: DWORD;

Ebp: DWORD;

Eip: DWORD;

SegCs: DWORD;

EFlags: DWORD;

Esp: DWORD;

SegSs: DWORD;

end;

从这个结构中可以基本洞察多线程的基本原理:

1、在切换到另一个线程之前, 先把当前线程在寄存器中的数据保存在这个结构;

2、重新切回线程时, 再才这个结构中读出相关数据到寄存器, 从而继续运行...

压栈、出栈也是类似的道理.

一个程序包含若干子程序, 子程序中一般会有自己的参数或局部变量.

在执行这个子程序前, 应该先把寄存器中的相关数据暂存一下(子程序也要使用寄存器), 这就是所谓的压栈(PUSH);

等子程序执行完毕, 再把之前压到栈中的数据取回(而让程序继续执行), 这就是所谓的出栈(POP).

什么是 "栈"?

程序把内存划分了若干区域, 其中有 "全局数据区" 和 "局部数据区".

全局数据所在的位置叫 "堆";

局部数据(局部变量、局部常量、子程序参数)所在的位置叫 "栈", 也叫 "堆栈".

对 "堆" 和 "栈", 前人给出了不同的使用规则:

"堆" 中的数据一般是由下到上排列;

"栈" 的数据则完全相反, 是由下到上排列.

验证 "堆" 与 "栈" 不同的数据排列方式:

; Test17_1.asm

.386

.model flat, stdcall

include windows.inc

include kernel32.inc

include masm32.inc

include debug.inc

includelib kernel32.lib

includelib masm32.lib

includelib debug.lib

.data?

GlobalVal1 dd ?

GlobalVal2 dd ?

GlobalVal3 dd ?

.code

main proc

LOCAL LocalVal1:dword, LocalVal2:dword, LocalVal3:dword

;获取全局变量地址(地址是顺序递增的):

PrintHex offset GlobalVal1 ;00403054

PrintHex offset GlobalVal2 ;00403058

PrintHex offset GlobalVal3 ;0040305C

;获取局部变量地址(地址是顺序递减的):

lea eax, LocalVal1

PrintHex eax ;0012FFBC

lea eax, LocalVal2

PrintHex eax ;0012FFB8

lea eax, LocalVal3

PrintHex eax ;0012FFB4

ret

main endp

end main

压栈与出栈的顺序:

.386

.model flat, stdcall

include windows.inc

include kernel32.inc

include masm32.inc

include debug.inc

includelib kernel32.lib

includelib masm32.lib

includelib debug.lib

.data

val1 dd 111

val2 dd 222

val3 dd 333

.code

main proc

push val1

push val2

push val3

;压栈完毕, 接着出栈

pop val1

pop val2

pop val3

;查看取回的数据:

PrintDec val1 ;333

PrintDec val2 ;222

PrintDec val3 ;111

;怎么反了? 这就是常说的 "栈中的数据是先进后出"! 让后进的先出就好了.

ret

main endp

end main

根据 "栈" 先进后出的特点, 写一个变量换值的程序:

; Test17_3.asm

.386

.model flat, stdcall

include windows.inc

include kernel32.inc

include masm32.inc

include debug.inc

includelib kernel32.lib

includelib masm32.lib

includelib debug.lib

.data

val1 dd 111

val2 dd 999

.code

main proc

push val1

push val2

pop val1

pop val2

;现在 val1 和 val2 的值已经交换

PrintDec val1 ;999

PrintDec val2 ;111

ret

main endp

end main

如果仅是交换变量的值, 可以使用 XCHG 指令:

; Test17_4.asm

.386

.model flat, stdcall

include windows.inc

include kernel32.inc

include masm32.inc

include debug.inc

includelib kernel32.lib

includelib masm32.lib

includelib debug.lib

.data

val1 dd 111

val2 dd 999

.code

main proc

;xchg va1, val2 ;指令都不支持对两个变量直接操作, 需要用个寄存器中转下

mov eax, val1

xchg eax, val2

mov val1, eax

PrintDec val1 ;999

PrintDec val2 ;111

ret

main endp

end main

根据上面的原理, 也可以方便写出一个翻转字符串的函数:

; Test17_5.asm

.386

.model flat, stdcall

include windows.inc

include kernel32.inc

include masm32.inc

include debug.inc

includelib kernel32.lib

includelib masm32.lib

includelib debug.lib

.data

szText db 'Hello World!', 0

.code

main proc

;把字符串中的字符逐个压入栈中

mov ecx, sizeof szText - 1 ;把字符串长度(将要反复的次数)给 ecx, 没包括结束记号

xor esi, esi ;清空 esi, 准备用作数组索引

@@: movzx eax, szText[esi] ;循环读出并压栈

push eax

inc esi

loop @B

;从栈中逐个取出并写入字符串

mov ecx, sizeof szText - 1

xor esi, esi

@@: pop eax

mov szText[esi], al

inc esi

loop @B

PrintString szText ;!dlroW olleH

ret

main endp

end main

;做这个程序也有更好的方案, 譬如用 movs

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大生群体。无论你是计算机相关专业的生,还是对其他领域编程感兴趣的生,这些资源都能为你提供宝贵的学习和实践机。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值