【发布时间】:2020-05-05 20:26:13
【问题描述】:
非常简单的汇编介绍代码。
似乎可以通过gcc -o prog1 prog1.s 编译,然后./prog1 只是跳过一行并且什么都不显示,就像等待代码不询问的输入一样。怎么了?
在 VMware 上运行的 64 位 gNewSense 中使用 gcc (Debian 4.7.2-5) 4.7.2。
代码:
/*
int nums[] = {10, -21, -30, 45};
int main() {
int i, *p;
for (i = 0, p = nums; i != 4; i++, p++)
printf("%d\n", *p);
return 0;
}
*/
.data
nums: .int 10, -21, -30, 45
Sf: .string "%d\n" # string de formato para printf
.text
.globl main
main:
/********************************************************/
/* mantenha este trecho aqui e nao mexa - prologo !!! */
pushq %rbp
movq %rsp, %rbp
subq $16, %rsp
movq %rbx, -8(%rbp)
movq %r12, -16(%rbp)
/********************************************************/
movl $0, %ebx /* ebx = 0; */
movq $nums, %r12 /* r12 = &nums */
L1:
cmpl $4, %ebx /* if (ebx == 4) ? */
je L2 /* goto L2 */
movl (%r12), %eax /* eax = *r12 */
/*************************************************************/
/* este trecho imprime o valor de %eax (estraga %eax) */
movq $Sf, %rdi /* primeiro parametro (ponteiro)*/
movl %eax, %esi /* segundo parametro (inteiro) */
call printf /* chama a funcao da biblioteca */
/*************************************************************/
addl $1, %ebx /* ebx += 1; */
addq $4, %r12 /* r12 += 4; */
jmp L1 /* goto L1; */
L2:
/***************************************************************/
/* mantenha este trecho aqui e nao mexa - finalizacao!!!! */
movq $0, %rax /* rax = 0 (valor de retorno) */
movq -8(%rbp), %rbx
movq -16(%rbp), %r12
leave
ret
/***************************************************************/
【问题讨论】:
-
如果您可以将 cmets 翻译成英文并解释您期望的输出类型(我想与您上面列出的 C 程序的输出相同),事情会变得容易得多。
-
对我来说,它就像您评论中的 C 代码一样工作。你确定你正在编译和运行你认为的东西吗?
-
您应该在
call printf之前将%al归零,因为您不使用任何 SSE 寄存器作为参数。不过,这不太可能导致这个问题。您可以尝试通过strace运行程序,当然也可以使用调试器。 -
等等,我刚刚在 gNewSense 4 VM 中尝试过,我可以在那里重现问题。毕竟我也许能弄清楚这一点。
-
@Jester 关于需要将
%al归零是正确的。这样做,它的工作原理。完整的答案和解释很快就会到来。
标签: gcc assembly x86-64 calling-convention abi