- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在用汇编语言编写一些矩阵乘法代码。我不能使用变量,只能在堆栈上存储我需要的东西。该算法似乎工作正常,但我在最后两个代码块中使用寄存器的 IMUL 和 MOV 有问题。我在这里发布我的代码:
unsigned int m = 3; // raws of mat1
unsigned int n = 2; // columns of mat1
unsigned int k = 4; // columns of mat2
short int mat1[] = { -1,-2, 4,5, 4,-2 }; // first matrix
short int mat2[] = { 2,0,4,6, 0,2,-1,3 }; // second matrix
int mat3[1024]; // output matrix
__asm {
XOR EAX, EAX //mat1 raws counter
XOR EBX, EBX //mat2 columns counter
XOR EDX, EDX //mat1 columns(equal to mat2 raws) counter
XOR EDI, EDI //will contain sum of multiplications to be copied into output matrix
Loop1 : //determinates the raws of output matrix: mat3
XOR EBX, EBX //at the end of first raw, column counter is resetted
CMP m, EAX //if loopped mat1 m-raws times...
JZ Finale //...algortihm is over
INC EAX //increase mat1 raws counter
JMP Loop2
Loop2 : //determinates the columns of mat3
XOR EDX, EDX //at the end of the n-sums, mat1 column counter is resetted
XOR EDI, EDI //after sum of n-multiplications edi is resetted
CMP k, EBX //if multiplications/sums on this raw have been done...
JZ Loop1 //...go to next output matrix raw
INC EBX //increase mat2 columns counter
JMP Loop3
Loop3 : //determinates elements of mat3
CMP n, EDX //if the n-multiplacations/sums on first n-elements have been done...
JZ Loop2 //...skip to next n-elements
INC EDX //increase counter of the elements that will be multiplicate
JMP Stuffs //go to operations code block
Stuffs : //here code generates mat3 elements
#58 MOV SI, mat1[2 * ((EAX - 1) * 2 + (EDX - 1)] //moves to SI the [m-raws/n-clomumn] element of mat1
#59 IMUL SI, mat2[2 * ((EBX - 1) * 2 + (EDX - 1)] //multiplicates(with sign) SI and [n-raws/k-column] element of mat2
ADD DI, SI //sum the result in edi
CMP n, EDX //check the sums
JZ CopyResult //if n-sums have been done...
JMP Loop3 //...go to copy result into mat3
CopyResult :
#66 MOV mat3[4 * ((EAX - 1) * 4 + (EBX - 1))], EDI //copy value to output matrix mat3
JMP Loop3 //go to next n-elements
Finale :
}
{
unsigned int i, j, h;
printf("Output matrix:\n");
for (i = h = 0; i < m; i++) {
for (j = 0; j < k; j++, h++)
printf("%6d ", mat3[h]);
printf("\n");
}
}
在此代码中,编译器针对 mat1、mat2 和 mat3 报告两种类型的错误引用 IMUL 和 MOV。他们在这里:
第 59 行和第 66 行的错误与 EDX 和 EBX 寄存器相同。
这个算法基本上好吗? (我测试了一些手动设置 索引,然后是最后一个,在调试期间它很好,但我无法完全测试它)。
我认为第一个错误取决于第二个错误,但如果我 不能以这种方式使用寄存器,我该如何计算输出?
最佳答案
与其尝试在寻址模式 ( which is impossible ) 中将多个寄存器按两个缩放,不如使用 add eax, 2
而不是 inc eax
。
此外,由于您的输出矩阵使用 32 位 int
,因此您应该进行 32 位数学计算。您在 DI 中生成一个值,然后使用第 66 行将该值加上 EDI 高半部分中的任何垃圾进行存储。
有点像 movsx esi, word ptr [rowstart + column]
/movsx eax, word ptr [offset_in_column + row]
/imul eax, esi
可能适用于(部分)内循环主体。我将让您在第一种寻址模式中按列递增,在第二种寻址模式中按行递增。
根据我认为您正在尝试做的事情,我认为您的算法可能是合理的。对于输出矩阵的每个元素,循环遍历一个矩阵中的一列和另一个矩阵中的一行。所以你只对输出矩阵的每个元素存储一次。不管你的循环是否真的这样做了,IDK:分支的丑陋程度让我很伤心。 (查看优化编译器输出的某个循环,然后是双重或三重嵌套循环。例如 http://gcc.godbolt.org/)。
嵌套循环的其他方法对于大型矩阵的性能可能更好或更差,但唯一真正好的方法(对于大型矩阵)涉及转置输入矩阵之一,以便您可以循环连续的内存元素一次在两个矩阵中(因为转置花费 O(n^2) 时间,但加快了重复遍历转置数组的 O(n^3) 步骤,因为它提供了更多缓存命中)。
(考虑到浮点 matmul 在科学计算中的普遍性,这是一个已经被广泛研究的主题,在代码的实验性调整中投入了大量精力。请参阅 BLAS 中 DGEMM 函数的各种实现。)
关于assembly - 汇编中的矩阵乘法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39176473/
我试图在图形模式下打印一个字符。通常当我打印我正在做的一个字符时: mov ah,14 ; ah=14 mov al,'x' int 10h ; print the character 这
我试图通过更改其中的一个字节来修改存储在内存中的字符串。我为此使用了 movb,但由于某种原因,给定内存位置的字节没有改变。 在 gdb 调试器上: 14 movb %al, (%r10) # nex
我一直在阅读一些汇编代码,并且开始发现调用指令实际上是与程序计数器相关的。 但是,每当我使用 Visual Studio 或 Windbg 进行调试时,它总是显示 call 0xFFFFFF ...这
我最近一直在使用 Visual C++ 中的内联汇编,我想知道是否可以直接向堆栈上的局部变量添加值,例如: push 5 add [esp], 7 这样做可以吗?我问这个问题是因为我在执行此操作时随机
我有下一个代码: mov al, -5 add al, 132 add al, 1 据我检查,溢出标志和进位标志将在第一个操作中设置,而在第二个操作中,仅设置溢出。 但我不明白为什么: 在无符号数中,
在 64 位 x86 汇编 nasm 中,如何将单个字节从寄存器移动到 .data 节中定义的内存位置? 我知道这有效 global _main section .data quotient db 0
我的汇编代码有问题。我想打印存储在寄存器 cx 中的数字,但是当我尝试打印它时,它打印的是 ascii 字符而不是 ascii 数字,所以我决定编写一个程序将 ascii char 转换为 ascii
为什么第 1B 行的跳转指令(例如)变成了 EBBD? 我知道“jmp”= EB但是BD是怎么计算的呢? 最佳答案 短跳转使用一个带符号的偏移量添加到 JMP 之后的指令地址。 例如,第一个 JMP
以下两者有什么区别: mov eax, [eax+4] 和 add eax, 4 mov eax, [eax] 如果不是,那么汇编器是否会选择哪个来进行某种优化? 最佳答案 这
看《The Shellcoder's Handbook》中的一些汇编和反汇编代码,发现一条指令的序列操作数是不一样的。 例如,在 assembly 上: mov ebx,0 并且,在反汇编时: mov
我有这个非常简单的汇编代码: start: add ax, 100 ; if ax overflow add to bx 1 jmp start 但我不知道如何检测 ax 寄存器溢出,有人可以帮
在 64 位 x86 汇编 nasm 中,如何将单个字节从寄存器移动到 .data 节中定义的内存位置? 我知道这有效 global _main section .data quotient db 0
我的汇编代码有问题。我想打印存储在寄存器 cx 中的数字,但是当我尝试打印它时,它打印的是 ascii 字符而不是 ascii 数字,所以我决定编写一个程序将 ascii char 转换为 ascii
我正在学习一些关于操作系统开发的教程,我发现了一篇关于多重引导 header 。这些是您必须定义的一些“神奇”值才能使用GRUB2。这些是命令: # Declare constants used f
为什么第 1B 行的跳转指令(例如)变成了 EBBD? 我知道“jmp”= EB但是BD是怎么计算的呢? 最佳答案 短跳转使用一个带符号的偏移量添加到 JMP 之后的指令地址。 例如,第一个 JMP
我正在尝试从内存中复制一些单词并使用汇编将其保存到另一个内存地址。我正在尝试为其编写代码,但我不确定其中的某些部分。我将简要描述我想要做什么。 源地址、目标地址和要复制的字数是函数的输入参数。 最佳答
当我们想要像这样创建一个初始化变量时: name db 'zara ali' 我们创建了一个字节大小变量,但我们在其中存储了一个字符串 这怎么可能?? 当我们使用这条指令时: MOV ecx, nam
我还是汇编的新手,我还不知道汇编中的许多命令代码。我想在 16 位寄存器中进行除法。我想打印它的内容。我知道我需要将寄存器的内容转换为 ASCII 进行打印,但同样,我的问题是除法。请帮我。 比如cx
使用有什么区别: c.eq.s $1, $2 bc1t L2 并使用: beq $1, $2, L2 如果他们做同样的事情,为什么有两种分支方式?如果它们不同,那么它们各自的好处是什么
源代码: int main() { int i; for(i=0, i : push rbp 2. 0x000055555555463b :
我是一名优秀的程序员,十分优秀!