在过程中操作运行时堆栈

2023-12-13

我正在开发一个包含两个过程的程序。一种是将 N 个无符号双字的数组压入堆栈,另一种将 N 个无符号双字从堆栈中弹出并将它们存储在数组中。我能够成功地将所有元素推入堆栈,但随后该过程无法返回主程序,因为堆栈指针(esp注册)已更改。

我已经能够回到main通过操纵esp注册以便保存返回地址,然后我将该地址重新加载到esp在我回来之前。但是,当调用下一个过程时,我推送到堆栈的条目已被覆盖。

在程序中工作时是否有正确的方法将数据保存在堆栈中?

这是我的一些代码:

Main程序:

main PROC
main_loop:
; Main menu
    mov edx, offset choicePrompt
    call WriteString

    read_input:
        call ReadInt
        jno good_input
        jmp main_loop

    good_input:
        cmp eax, 0
        je create_vector
        cmp eax, 1
        je array_stack
        cmp eax, 2
        je stack_array
        cmp eax, -1
        je end_program

        call crlf
        jmp main_loop

    create_vector:
        call CreateVector
        jmp end_options

    array_stack:
        call ArrayToStack
        jmp end_options

    stack_array:
        call StackToArray
        jmp end_options

    end_options:
        call crlf
        jmp main_loop

end_program:
    mov edx, offset exitPrompt
    call WriteString
    call crlf
exit
main ENDP

将数组压入栈中数组到堆栈程序:

mov esi, offset Vector
mov ebx, N
dec ebx
mov eax, 0
mov ecx, -1

push_array_loop:
    inc ecx
    mov al, [esi + ecx]
    push eax
    mov [esi + ecx], byte ptr(0)
    cmp ecx, ebx
    jl push_array_loop

将堆栈写入控制台堆栈到数组程序:

mov eax, N
mov ebx, 4
mul ebx
mov ebx, eax
mov ecx, 0
write_stack_loop:
    mov eax, [esp + ecx]
    add ecx, 4
    call WriteDec
    mov edx, offset spacePrompt
    call WriteString
    cmp ecx, ebx
    jl write_stack_loop

检查你的场所。在第一段中,您讨论了一个推入 N 个无符号数组的过程双词到堆栈,但您的代码处理 N 个无符号数组bytes.

此外,我观察到控制台上的输出将以相反的顺序(到数组),并且您的代码在读取输入数组时将其归零。我已将所有这些内容保留在以下解决方案中。

前 2 个片段将保留ECX and EDX。他们确实搞砸了EAX.

对您的编码问题的真正解释当然是查看每个步骤如何修改堆栈。仔细观察!

ArrayToStack:

                                                  [ ret ]
                                                  ^ esp

    mov     eax, N                 ; The number of array elements is a runtime value
    dec     eax
    shl     eax, 2
    sub     esp, eax

                             <-- eax = (N-1)*4 -->
                             [     ][ ... ][     ][ ret ]
                             ^ esp

    push    dword ptr [esp + eax]

                      [ ret ][     ][ ... ][     ][     ]
                      ^ esp

    push    ecx
    push    edx

        [ edx ][ ecx ][ ret ][     ][ ... ][     ][     ]
        ^ esp

    xor     ecx, ecx
  ToStack:
    xor     edx, edx
    xchg    dl, [Vector + ecx]     ; Reading byte-sized element while zeroing the source
    mov     [esp + 12 + eax], edx
    inc     ecx
    sub     eax, 4
    jnb     ToStack

        [ edx ][ ecx ][ ret ][ a_N ][ ... ][ a_2 ][ a_1 ]
        ^ esp                ^ esp+12

    pop     edx
    pop     ecx

                      [ ret ][ a_N ][ ... ][ a_2 ][ a_1 ]
                      ^ esp

    ret                            ; EAX ends at -4

                             [ a_N ][ ... ][ a_2 ][ a_1 ]
                             ^ esp


StackToConsoleProcedure:

                      [ ret ][ a_N ][ ... ][ a_2 ][ a_1 ]
                      ^ esp

    push    ecx
    push    edx

        [ edx ][ ecx ][ ret ][ a_N ][ ... ][ a_2 ][ a_1 ]
        ^ esp                ^ esp+12

    xor     ecx, ecx
  FromStack:
    mov     eax, [esp + 12 + ecx*4]
    call    WriteDec
    mov     edx, offset spacePrompt
    call    WriteString
    inc     ecx
    cmp     ecx, N
    jb      FromStack
    shl     ecx, 2                 ; ECX = N*4
    mov     eax, [esp + 8]         ; Fetch return address
    mov     [esp + 8 + ecx], eax

                      <-------- ecx = N*4 ------->
        [ edx ][ ecx ][     ][ a_N ][ ... ][ a_2 ][ ret ]
        ^ esp         ^ esp+8

    mov     eax, ecx
    pop     edx
    pop     ecx

                      <-------- eax = N*4 ------->
                      [     ][ a_N ][ ... ][ a_2 ][ ret ]
                      ^ esp

    add     esp, eax

                                                  [ ret ]
                                                  ^ esp


    ret                            ; EAX ends at N*4

如果不需要保存ECX and EDX寄存器,但仍然允许EAX被殴打:

ArrayToStack:
    mov     eax, N
    dec     eax
    shl     eax, 2
    sub     esp, eax
    push    dword ptr [esp + eax]
    xor     ecx, ecx
  ToStack:
    xor     edx, edx
    xchg    dl, [Vector + ecx]
    mov     [esp + 4 + eax], edx
    inc     ecx
    sub     eax, 4
    jnb     ToStack
    ret

StackToConsoleProcedure:
    xor     ecx, ecx
  Fromtack:
    mov     eax, [esp + 4 + ecx*4]
    call    WriteDec
    mov     edx, offset spacePrompt
    call    WriteString
    inc     ecx
    cmp     ecx, N
    jb      FromStack
    shl     ecx, 2
    pop     eax
    add     esp, ecx
    push    eax
    ret
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在过程中操作运行时堆栈 的相关文章

  • 使用按位运算符相乘

    我想知道如何使用按位运算符将一系列二进制位相乘 但是 我有兴趣这样做来查找二进制值的十进制小数值 这是我正在尝试做的一个例子 假设 1010010 我想使用每个单独的位 以便将其计算为 1 2 1 0 2 2 1 2 3 0 2 4 虽然我
  • Grub 和进入实模式(低级汇编语言编程)

    我一直在开发一个玩具操作系统 并一直使用 grub 作为我的引导加载程序 最近尝试使用 VGA 时 我发现无法使用硬件中断 我发现这是因为我被 grub 置于保护模式 有人知道如何在不删除 grub 的情况下回到实模式吗 如果您使用 GRU
  • 使用 Gas 生成与位置无关的代码 (-fPIC)

    我尝试在 x86 64 上创建共享库但失败 问题归结为以下代码 请不要介意 它没有多大意义 section data newline ascii n section text globl write newline type write n
  • PAE(物理地址扩展)如何实现大于4GB的地址空间?

    维基百科文章的摘录物理地址扩展 http en wikipedia org wiki Physical Address Extension x86 处理器硬件架构通过用于选择附加内存的附加地址线进行了增强 因此物理地址大小从 32 位增加到
  • 如何在WinMobile6上启用ARMv6非对齐访问?

    ARMv6 引入了一个很棒的功能 未对齐的内存访问 这使得代码中的某些事情变得更加简单和更快 但微软只在winCE6中提供了API 现在大多数 PDA 都基于 WinMobile6 基于 CE 5 x 默认情况下禁用未对齐访问 我尝试在 C
  • 在 Intel x86 架构上使用非 AVX 指令移动 xmm 整数寄存器值

    我有以下问题 需要使用 AVX2 以外的任何工具来解决 我有 3 个值存储在 m128i 变量中 不需要第四个值 需要将这些值移动 4 3 5 我需要两个功能 一个用于按这些值进行右逻辑移位 另一个用于左逻辑移位 有谁知道使用 SSE AV
  • Android NDK 代码中的 SIGILL

    我在市场上有一个 NDK 应用程序 并获得了有关以下内容的本机崩溃报告 SIGILL信号 我使用 Google Breakpad 生成本机崩溃报告 以下是详细信息 我的应用程序是为armeabi v7a with霓虹灯支持 它在 NVIDI
  • 当 mov 指令导致页面错误并且在 x86 上禁用中断时会发生什么?

    我最近在自定义 Linux 内核 2 6 31 5 x86 驱动程序中遇到一个问题 其中 copy to user 会定期不将任何字节复制到用户空间 它将返回传递给它的字节数 表明它没有复制任何内容 经过代码检查 我们发现代码在调用 cop
  • 一个地址有多少字节? [复制]

    这个问题在这里已经有答案了 在64位机器上 我们知道一个地址是8个字节 然而 我并不完全清楚一个地址中有多少字节的信息 虚拟内存中的每个字节都有一个地址吗 或者内存中的每 64 位都有一个地址 还是取决于架构 如果这取决于架构 那么我应该如
  • Polygot 包含 nasm/yasm 和 C 的文件

    我有一堆幻数 我想将它们包含在由 nasm 或 yasm 编译的 C 程序和汇编文件中 在纯 C 语言中 该文件看起来像是一系列定义 例如 define BLESS 55378008 define ANSWER 42 在 nasm 或 ya
  • long double(GCC 特定)和 __float128

    我正在寻找有关的详细信息long double and float128在 GCC x86 中 更多是出于好奇而不是因为实际问题 可能很少有人需要这些 我只是有史以来第一次 truly需要一个double 但我想知道你的工具箱里有什么以及它
  • 从 DX:AX 寄存器转移到单个 32 位寄存器

    我在添加 16 位乘法的乘积时遇到问题 我想将一年 例如 2015 年 乘以 365 为此 我 mov dx 0 to clear the register mov ax cx cx holds the year such as 2015
  • 在 x86 程序集中打印寄存器值的简单方法

    我需要在 8086 Assembly 中编写一个程序 接收来自用户的数据 进行一些数学计算并在屏幕上打印答案 我已经编写了程序的所有部分并且一切正常 但我不知道如何打印号码显示到屏幕上 在我所有计算结束时 答案是 AX 它被视为无符号 16
  • 从c调用汇编函数

    我试图从 c 调用汇编函数 但我不断收到错误 text globl integrate type integrate function integrate push ebp mov esp ebp mov 0 edi start loop
  • 为什么 mov %ax, %ds 汇编+反汇编为 mov %eax,%ds,与原来不一致?

    test S text global start start xor ax ax mov ax ds mov ax ss mov ax es mov ax fs mov ax gs 我通过这样做得到了反汇编代码文件 x86 64 elf g
  • 为什么前向引用 ADR 指令在 Thumb 代码中以偶数偏移进行汇编?

    To bx对于 Thumb 函数 需要设置地址的最低有效位 GNU 作为文档states https sourceware org binutils docs as ARM Opcodes html当地址是从一个生成时这是如何工作的adr伪
  • Windows 上 PE 文件 (exe) 的最小文件大小是多少?以及最小内存分配? [复制]

    这个问题在这里已经有答案了 Windows 上 PE 文件 exe 的最小文件大小是多少 以及最小内存分配 我 使用 VS 10 附带的 MASM ml exe 和 link exe 组装了以下代码 我不能忽略 kernel32 lib 和
  • 汇编语言程序中连续两次相乘

    我正在使用 8086 模拟器以及 DOSBOX 和 MASM 我知道当我们将 8 位与 8 位相乘时 答案将是 16 位 al 8 bit ax 当我们将 16 位与 16 位相乘时 答案将是 32 位 ax 16 bit dx ax 但如
  • 如何将 asm 着色器编译为 fxo 文件?

    我有一个已编译的 fxo 着色器 我正在尝试对其进行稍微编辑 仅调整一些常量 使用 fxdis https code google com archive p fxdis d3d1x https code google com archiv
  • 如何从程序内部获取指向程序的特定可执行文件部分的指针? (也许是诽谤)

    我在 Linux 环境中 需要编写一个程序来检索放置在其可执行文件的某个部分中的一些数据 那么 如何从程序内部获取指向程序某个部分 通过其名称 的指针呢 我知道可以使用elf getdata 将节的索引作为参数传递给 get 和Elf Da

随机推荐

  • 为什么大多数 java.util.Date 方法被弃用?

    当您查看 java util Date 类的 javadoc 时 会发现大多数方法都已弃用 为什么要这样做 嗯 有两个相关的原因 这是日期和时间概念的一个非常糟糕的实现 它被Calendar class The Calendar类虽然有所改
  • 有没有办法预测刚体与墙壁和其他移动刚体的去向?

    我正在开发一款空气曲棍球游戏 我需要 AI 来预测球的去向 以便球能够击中球 而不仅仅是追球 问题是人工智能无法预测它和冰球将撞到的墙壁 它的预测是这样的 这是我现在使用的代码 if isEnemy if puck transform po
  • 自定义 Android Intent.ACTION_SEND

    我正在使用 Intent 来共享 url 和主题 在此意图过滤器中显示所有共享应用程序 我只想要 facebook gmail message skype twitter 弹出窗口中的这些选项 是否可以自定义共享意图过滤器 Intent s
  • INET_NTOA 和 INET_ATON 的 .NET 等效项

    任何 C Net 等效方法 或 INET NTOA 和 INET ATON 的托管代码示例 The IPAddress类有静态方法 HostToNetworkOrder NetworkToHostOrder 具有各种过载
  • 查找标签之间的文本并将其与标签一起替换

    我正在使用以下正则表达式模式来查找之间的文本 code and code tags lt code code 它返回我这两个标签之间的任何内容 例如这 code return Hi There code 给我return Hi There
  • python exe中的图像文件夹放在哪里?

    我已经将我设计的一个python游戏转换成了exe 运行 exe 本身会导致它闪烁然后关闭 这意味着发生了错误 从命令提示符运行它也会导致错误 但会记录它 Cannot load image Playfield png Couldn t o
  • urlread()、urlwrite() 不适用于 Octave for Windows 中的 https 页面

    当我使用 Cygwin 中安装的 Octave 3 8 1 时 我可以成功下载 https 页面 如下所示 urlwrite https www google com downloaded html 但是 当我使用 Windows 7 SP
  • 为什么某些 .wav 文件无法在 Firefox 中解码

    我有一个网页 由于某些原因可以解码波形文件 Chrome 和 Safari 似乎运行良好 Firefox 有时无法解码该文件并给出错误 传递给decodeAudioData 的缓冲区包含无法成功解码的无效内容 我创建了一个jsfiddle这
  • Typescript:属性的类型依赖于同一对象中的另一个属性

    我有一个具有两个属性的 TypeScript 接口 type string and args object The args可能具有不同的属性 具体取决于type 我需要应用什么类型定义args这样编译器 自动完成就会知道允许哪些属性arg
  • 使用 .htaccess 重写多个参数的 URL

    我想使用 htaccess 重写 url 请阅读代码 你就会明白我的意思 My URL article php id 1 title example 在 htaccess 中使用它 RewriteRule article 0 9 0 9a
  • Matlab bsxfun()代码

    这是做什么的 u 5 6 s 1 1 data1 randn 10 1 1 ones 10 1 data2 randn 10 1 ones 10 1 data data1 data2 deviance bsxfun minus data u
  • 如何将 Protractor 测试用例与 Hiptest 集成?

    对于使用 Angular js 制作的网站 我们的组织使用 Protractor 作为自动化测试用例的工具 我们的组织提出了一个名为 HipTest 的新工具来管理测试用例自动化 如何将量角器测试用例与 HipTest 集成 我访问了以下链
  • 无论页面刷新如何,持续计数器

    我有一段 jQuery 目前每 5 秒将数字增加 1 我遇到的问题是它的客户端 因此每次刷新页面时它都会重置 相反 我希望即使您离开站点并且无论您刷新页面多少次 计数器也能继续 这就是为什么我认为 PHP 等服务器端脚本更适合我的用例 如果
  • jQuery 验证插件 - 密码检查 - 最低要求 - 正则表达式

    我的密码检查器有点问题 有一个包含一些字段的注册表 我使用 jQuery Validate 插件来验证用户输入 除了密码验证之外 一切都有效 密码应满足一些最低要求 最小长度 8 gt 我只使用 minlength 8 至少一个小写字符 至
  • 奇怪的DNS服务器导致Hadoop和HBase出现故障

    我的网络有一些奇怪的 据我所知 DNS 服务器 这会导致 Hadoop 或 HBase 出现故障 它将我的主机名解析为我的机器不知道的某个地址 即没有这样的接口 如果 etc hosts 中有以下条目 Hadoop 确实可以工作 127 0
  • 将 QDate 转换为秒

    我的日期来自QDateTimeEdit并将其转换为秒 如下所示 import time from datetime import datetime date self ui dateTimeEdit date toString dd MM
  • 如果下面行中的值非空,则连接列标题

    我有一个表格 其中的数据格式如下 Data 我希望完成的表格具有要填充的空白列 如下面突出显示的那样 Finished Table 因此 我需要一个公式或 VBA 来返回并连接每行中非空白单元格的标题 使用以下内容作为数组公式 TEXTJO
  • 仅创建创建表语句中的第一个表

    表 credentials 确实显示在 adb shell 中 我检查了 logcat 它似乎没有报告问题 private static final String DATABASE CREATE create table credentia
  • Scala 工具的现状如何?

    在过去的一年里 我听到了越来越多关于 Scala 语言的炒作 我知道有几个现有项目计划将 Scala 支持与 IDE 集成 然而 整合到底有多好并不总是很清楚 他们目前是否像 Eclipse 和 Netbeans 对 Java 语言一样支持
  • 在过程中操作运行时堆栈

    我正在开发一个包含两个过程的程序 一种是将 N 个无符号双字的数组压入堆栈 另一种将 N 个无符号双字从堆栈中弹出并将它们存储在数组中 我能够成功地将所有元素推入堆栈 但随后该过程无法返回主程序 因为堆栈指针 esp注册 已更改 我已经能够