- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我正在学习 ASM 语言并在 Ubuntu Eclipse C++ 上试用 IMUL 函数,但出于某种原因,我似乎无法从我的代码中获得所需的输出。
Required:
Multiply the negative elements of an integer array int_array by a specified integer inum
这是我的代码:
C 代码:
#include <stdio.h>
extern void multiply_function();
// Variables
int iaver, inum;
int int_ar[10] = {1,2,3,4,-9,6,7,8,9,10};
int main()
{
inum = 2;
multiply_function();
for(int i=0; i<10; i++){
printf("%d ",int_ar[i]);
}
}
ASM代码:
extern int_ar
extern inum
global multiply_function
multiply_function:
enter 0,0
mov ecx, 10
mov eax, inum
multiply_loop:
cmp [int_ar +ecx*4-4], dword 0
jg .ifpositive
mov ebx, [int_ar +ecx*4-4]
imul ebx
cdq
mov [int_ar +ecx*4-4], eax
loop multiply_loop
leave
ret
.ifpositive:
loop multiply_loop
leave
ret
对于数组:{1,2,3,4,-9,6,7,8,9,10}
和 inum
,我得到输出 {1,2,3,4,-1210688460,6,7,8,9,10}
暗示发生了某种溢出。
对于 x86 汇编语言中的 IMUL 函数如何工作,我是否遗漏或理解错误?
我期望的输出是 {1,2,3,4,-18,6,7,8,9,10}
我对上述任务的思考过程:
1) 查找数组中哪些数组元素为负数,对于每一个找到的正数元素,什么也不做,继续循环到下一个元素
cmp [int_ar +ecx*4-4], dword 0
jg .ifpositive
.ifpositive:
loop multiply_loop
leave
ret
2) 找到负元素后,将其值移动到寄存器 EBX 中,该寄存器将用作 IMUL SRC 函数中的 SRC。然后将寄存器 EAX 扩展到 EAX-EDX,结果存储在:
mov ebx, [int_ar +ecx*4-4]
imul ebx
cdq
3) 使用 MOV 将结果移动到数组的负元素中:
mov [int_ar +ecx*4-4], eax
4) 循环到下一个数组元素,重复上面的1)-3)
最佳答案
如果我们忽略低效和不需要的代码并处理真正的问题,它归结为这条指令:
mov eax, inum
什么是 inum
?您在 C 中创建并初始化了一个名为 inum
的全局变量与:
int iaver, inum;
[snip]
inum = 2;
inum
作为一个变量本质上是一个包含 int
的内存位置的标签(32 位值)。在您的汇编代码中,您需要处理 inum
作为指向值的指针,而不是值本身。在您的汇编代码中,您需要更改:
mov eax, inum
到:
mov eax, [inum]
你的版本所做的是移动地址 inum
进入EAX。您的代码最终将变量的地址乘以数组中的负数。这会导致您看到错误的值。 inum
周围的方括号告诉汇编器你想处理 inum
作为内存操作数,并且您想将 32 位值移动到 inum
进入EAX。
您似乎正在创建一个 32 位程序并在 32 位 Ubuntu 上运行它。我可以通过返回的错误值 -1210688460 推断出 32 位 Linux 的可能性。 -1210688460 = 0xB7D65C34 除以 -9 得到 804A06C。 32位Linux上的程序通常从0x8048000开始加载
无论是在32位Linux还是64位Linux上运行,与32位C/C++程序链接的汇编代码都需要遵守CDECL calling convention :
cdecl
The cdecl (which stands for C declaration) is a calling convention that originates from the C programming language and is used by many C compilers for the x86 architecture.1 In cdecl, subroutine arguments are passed on the stack. Integer values and memory addresses are returned in the EAX register, floating point values in the ST0 x87 register. Registers EAX, ECX, and EDX are caller-saved, and the rest are callee-saved. The x87 floating point registers ST0 to ST7 must be empty (popped or freed) when calling a new function, and ST1 to ST7 must be empty on exiting a function. ST0 must also be empty when not used for returning a value.
您的代码破坏了 EAX、EBX、ECX 和 EDX。您可以随意销毁 EAX、ECX 和 EDX 的内容,但您必须保留 EBX。如果不这样做,可能会导致调用该函数的 C 代码出现问题。在你执行 enter 0,0
之后说明你可以push ebx
就在每个 leave
之前你可以做的说明pop ebx
如果您要使用 -O1
, -O2
, 或 -O3
GCC 编译器选项可优化您的程序可能无法按预期工作或完全崩溃。
关于c - 使用 IMUL 指令将数组中的值相乘会产生不正确的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49222679/
这个问题已经有答案了: How to do case insensitive string comparison? (23 个回答) 已关闭 3 年前。 用户在我的输入栏中写入“足球”,然后执行第 6
啊,不习惯 javascript 中的字符串。 character_id= + id + correct= + correctOrIncorrect 这就是我需要制作成字符串的内容。如果您无法猜测字符
$(function() { var base_price = 0; CalculatePrice(); $(".math1").on('change', function(e) { Calc
我找不到任何文章回答问题:将Spinnaker部署到Spinnaker将管理的同一Kubernetes集群是否安全/正确?我主要是指生产,HA部署。 最佳答案 我认为Spinnaker和Kuberne
我正在使用MSVC在Windows上从源代码(官方源代码发布,而不是从仓库中)构建Qt5(Qt 5.15.0)。 我正在设置环境。变量,依赖项等,然后运行具有1600万个选项的configure,最后
我需要打印一个包含重复单词的数组。我的数组已经可以工作,但我不知道如何正确计算单词数。我已经知道,当我的索引计数器 (i) 为 49 时,并且当 (i) 想要计数到 50 时,我会收到错误,但我不知道
我正在遵循一个指南,该指南允许 Google map 屏幕根据屏幕尺寸禁用滚动。我唯一挣扎的部分是编写一个代码,当我手动调整屏幕大小时动态更改 True/False 值。 这是我按照说明操作的网站,但
我有一个类“FileButton”。它的目的是将文件链接到 JButton,FileButton 继承自 JButton。子类继承自此以使用链接到按钮的文件做有用的事情。 JingleCardButt
我的 friend 数组只返回一个数字而不是所有数字。 ($myfriends = 3) 应该是…… ($myfriends = 3 5 7 8 9 12). 如果我让它进入 while 循环……整个
这个问题在这里已经有了答案: Is there a workaround to make CSS classes with names that start with numbers valid?
我正在制作一个 JavaScript 函数,当调整窗口大小时,它会自动将 div 的大小调整为与窗口相同的宽度/高度。 该功能非常基本,但我注意到在调整窗口大小时出现明显的“绘制”滞后。在 JS fi
此问题的基本视觉效果可在 http://sevenx.de/demo/bootstrap-carousel/inc.carousel/tabbed-slider.html 获得。 - 如果你想看一看。
我明白,如果我想从函数返回一个字符串文字或一个数组,我应该将其声明为静态的,这样当被调用的函数被返回时,内容就不会“消亡”。 但我的问题是,当我在函数内部使用 malloc 分配内存时会怎样? 在下面
在 mySQL 数据库中存储 true/false/1/0 值最合适(读取数据消耗最少)的数据字段是什么? 我以前使用过一个字符长的 tinyint,但我不确定它是否是最佳解决方案? 谢谢! 最佳答案
我想一次读取并处理CSV文件第一行中的条目(例如打印)。我假设使用Unix风格的\n换行符,没有条目长度超过255个字符,并且(现在)在EOF之前有一个换行符。这意味着它是fgets()后跟strto
所以,我们都知道 -1 > 2u == true 的 C/C++ 有符号/无符号比较规则,并且我有一种情况,我想有效地实现“正确”比较。 我的问题是,考虑到人们熟悉的尽可能多的架构,哪种方法更有效。显
**摘要:**文章的标题看似自相矛盾。 本文分享自华为云社区《Java异常处理:如何写出“正确”但被编译器认为有语法错误的程序》,作者: Jerry Wang 。 文章的标题看似自相矛盾,然而我在“正
我有一个数据框,看起来像: dataDemo % mutate_each(funs(ifelse(. == '.', REF, as.character(.))), -POS) # POS REF
有人可以帮助我使用 VBScript 重新格式化/正确格式化带分隔符的文本文件吗? 我有一个文本文件 ^分界如下: AGREE^NAME^ADD1^ADD2^ADD3^ADD4^PCODE^BAL^A
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引起辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the he
我是一名优秀的程序员,十分优秀!