【发布时间】:2014-12-03 22:30:29
【问题描述】:
作为一项家庭作业,我们需要使用由 C 程序驱动的汇编程序来计算调和平均值。
我们使用的是 64 位 linux 机器,需要使用 64 位浮点数。
我是大会的新手。对于任何不良的编码习惯或我的代码完全错误,我深表歉意。
代码的问题是结果仅返回以浮点格式输入的最后一个数字。我不知道错误发生在哪里,虽然我相信它在于addDen 函数。
例如:如果您要输入数字 5、6、7、8,结果将返回 8.0000。
这是我的汇编程序代码:
;Assembly function that computs the harmonic mean
;of an array of 64-bit floating-point numbers.
;Retrieves input using a C program.
;
;Harmonic mean is defined as Sum(n/((1/x1) + (1/x2) + ... + (1/xn)))
;
; expects:
; RDI - address of array
; RSI - length of the array
; returns
; XMMO - the harmonic average of array's values
global harmonicMean
section .data
Zero dd 0.0
One dd 1.0
section .text
harmonicMean:
push rbp
mov rbp, rsp ;C prologue
movss xmm10, [Zero] ;Holds tally of denominator
cvtsi2ss xmm0, rsi ;Take length and put it into xmm0 register
.whileLoop:
cmp rsi, 0 ;Is the length of array 0?
je .endwhile
call addDen ;Compute a denominator value and add it to sum
add rdi, 4 ;Add size of float to address
dec rsi ;Decrease the length
jmp .whileLoop
.endwhile:
divss xmm0, xmm10
leave
ret
;Calculates a number in the denominator
addDen:
push rdi
movss xmm8, [One]
movss xmm9, [rdi]
divss xmm8, xmm9
addss xmm10, xmm8
pop rdi
ret
为了重现逻辑错误,我还将包括我的驱动程序:
/*
* Harmonic Mean Driver
* Tyler Weaver
* 03-12-2014
*/
#include<stdio.h>
#define ARRAYSIZE 4
double harmonicMean(double *, unsigned);
int main(int argc, char **argv) {
int i;
double ary[ARRAYSIZE];
double hm;
printf("Enter %d f.p. values: ", ARRAYSIZE);
for (i = 0; i < ARRAYSIZE; i++) {
scanf(" %lf", &ary[i]);
}
hm = harmonicMean(ary, ARRAYSIZE);
printf("asm: harmonic mean is %lf\n", hm);
return 0;
}
任何帮助将不胜感激!
【问题讨论】:
-
double *和unsigned的大小是否与RDI和RSI的大小相同?建议printf("%zu %zu\n", sizeof (double*), sizeof (unsigned));验证。 -
它们应该分别是 4 个字节。我们被告知对驱动程序使用双重和无符号。在任务详情中。我是Assembly的新手,所以我不知道这是否会溢出寄存器。数组会更长,但 RDI 寄存器应该只保存数组的前 4 个字节。
-
同意应该每个都是4个字节。 C 代码是否使用
printf("%zu %zu\n", sizeof (double*), sizeof (unsigned));报告? -
1) 我怀疑“
RDI寄存器应该只保存数组的前 4 个字节”。RDI应该保存数组的地址。 2) 为什么add rdi, 4 ;Add size of float to addressdouble通常是 8 个字节? -
是的,
float与double之间似乎存在混淆。你传入一个双精度数组,但几乎所有的 asm 代码都需要浮点数:你使用ss指令,假设大小为 4,你也返回一个浮点数。
标签: c linux assembly 64-bit average