这个 x86-64 addq 指令是什么意思,它只有一个操作数? (摘自CSAPP书第3版)
What does this x86-64 addq instruction mean, which only have one operand? (From CSAPP book 3rd Edition)
在下面的指令中,addq是如何工作的?它只有一个操作数,书中声称它递增 %rdx,但 %rdx 不在此指令中。我很困惑...
这是来自 Computer Systems A Programmers Perspective,第 3 版一书。
正如@Jester 在评论中指出的那样。这确实是一个错误。
我实际上输入了程序并使用 linux 上的 gcc 编译了它。下面是结果。
C程序:badcnt.c
/*
* badcnt.c - An improperly synchronized counter program
*/
#include <stdlib.h>
#include <pthread.h>
#include <stdio.h>
void *thread(void *vargp); /* Thread routine prototype */
/* Global shared variable */
volatile int cnt = 0; /* Counter */
int main(int argc, char **argv)
{
int niters;
pthread_t tid1, tid2;
/* Check input argument */
if (argc != 2) {
printf("usage: %s <niters>\n", argv[0]);
exit(0);
}
niters = atoi(argv[1]);
/* Create threads and wait for them to finish */
pthread_create(&tid1, NULL, thread, &niters);
pthread_create(&tid2, NULL, thread, &niters);
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
/* Check result */
if (cnt != (2 * niters))
printf("BOOM! cnt=%d\n", cnt);
else
printf("OK cnt=%d\n", cnt);
exit(0);
}
/* Thread routine */
void *thread(void *vargp)
{
int i, niters = *((int *)vargp);
for (i = 0; i < niters; i++)
cnt++;
return NULL;
}
使用 gcc 6.3.0 编译
$ gcc -pthread -Og -S badcnt.c
以下是badcnt.s
中的内容
.file "badcnt.c"
.text
.globl thread
.type thread, @function
thread:
.LFB20:
.cfi_startproc
movl (%rdi), %ecx
movl [=11=], %edx
jmp .L2
.L3:
movl cnt(%rip), %eax
addl , %eax
movl %eax, cnt(%rip)
addl , %edx
.L2:
cmpl %ecx, %edx
jl .L3
movl [=11=], %eax
ret
.cfi_endproc
.LFE20:
.size thread, .-thread
.section .rodata.str1.1,"aMS",@progbits,1
.LC0:
.string "usage: %s <niters>\n"
.LC1:
.string "BOOM! cnt=%d\n"
.LC2:
.string "OK cnt=%d\n"
.text
.globl main
.type main, @function
main:
.LFB19:
.cfi_startproc
subq , %rsp
.cfi_def_cfa_offset 48
cmpl , %edi
je .L5
movq (%rsi), %rsi
movl $.LC0, %edi
movl [=11=], %eax
call printf
movl [=11=], %edi
call exit
.L5:
movq 8(%rsi), %rdi
movl , %edx
movl [=11=], %esi
call strtol
movl %eax, 28(%rsp)
leaq 28(%rsp), %rcx
movl $thread, %edx
movl [=11=], %esi
leaq 16(%rsp), %rdi
call pthread_create
leaq 28(%rsp), %rcx
movl $thread, %edx
movl [=11=], %esi
leaq 8(%rsp), %rdi
call pthread_create
movl [=11=], %esi
movq 16(%rsp), %rdi
call pthread_join
movl [=11=], %esi
movq 8(%rsp), %rdi
call pthread_join
movl 28(%rsp), %eax
addl %eax, %eax
movl cnt(%rip), %edx
cmpl %edx, %eax
je .L6
movl cnt(%rip), %esi
movl $.LC1, %edi
movl [=11=], %eax
call printf
.L7:
movl [=11=], %edi
call exit
.L6:
movl cnt(%rip), %esi
movl $.LC2, %edi
movl [=11=], %eax
call printf
jmp .L7
.cfi_endproc
.LFE19:
.size main, .-main
.globl cnt
.bss
.align 4
.type cnt, @object
.size cnt, 4
cnt:
.zero 4
.ident "GCC: (GNU) 6.3.0"
.section .note.GNU-stack,"",@progbits
所以证实了书上的错误
在下面的指令中,addq是如何工作的?它只有一个操作数,书中声称它递增 %rdx,但 %rdx 不在此指令中。我很困惑...
这是来自 Computer Systems A Programmers Perspective,第 3 版一书。
正如@Jester 在评论中指出的那样。这确实是一个错误。 我实际上输入了程序并使用 linux 上的 gcc 编译了它。下面是结果。
C程序:badcnt.c
/*
* badcnt.c - An improperly synchronized counter program
*/
#include <stdlib.h>
#include <pthread.h>
#include <stdio.h>
void *thread(void *vargp); /* Thread routine prototype */
/* Global shared variable */
volatile int cnt = 0; /* Counter */
int main(int argc, char **argv)
{
int niters;
pthread_t tid1, tid2;
/* Check input argument */
if (argc != 2) {
printf("usage: %s <niters>\n", argv[0]);
exit(0);
}
niters = atoi(argv[1]);
/* Create threads and wait for them to finish */
pthread_create(&tid1, NULL, thread, &niters);
pthread_create(&tid2, NULL, thread, &niters);
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
/* Check result */
if (cnt != (2 * niters))
printf("BOOM! cnt=%d\n", cnt);
else
printf("OK cnt=%d\n", cnt);
exit(0);
}
/* Thread routine */
void *thread(void *vargp)
{
int i, niters = *((int *)vargp);
for (i = 0; i < niters; i++)
cnt++;
return NULL;
}
使用 gcc 6.3.0 编译
$ gcc -pthread -Og -S badcnt.c
以下是badcnt.s
中的内容 .file "badcnt.c"
.text
.globl thread
.type thread, @function
thread:
.LFB20:
.cfi_startproc
movl (%rdi), %ecx
movl [=11=], %edx
jmp .L2
.L3:
movl cnt(%rip), %eax
addl , %eax
movl %eax, cnt(%rip)
addl , %edx
.L2:
cmpl %ecx, %edx
jl .L3
movl [=11=], %eax
ret
.cfi_endproc
.LFE20:
.size thread, .-thread
.section .rodata.str1.1,"aMS",@progbits,1
.LC0:
.string "usage: %s <niters>\n"
.LC1:
.string "BOOM! cnt=%d\n"
.LC2:
.string "OK cnt=%d\n"
.text
.globl main
.type main, @function
main:
.LFB19:
.cfi_startproc
subq , %rsp
.cfi_def_cfa_offset 48
cmpl , %edi
je .L5
movq (%rsi), %rsi
movl $.LC0, %edi
movl [=11=], %eax
call printf
movl [=11=], %edi
call exit
.L5:
movq 8(%rsi), %rdi
movl , %edx
movl [=11=], %esi
call strtol
movl %eax, 28(%rsp)
leaq 28(%rsp), %rcx
movl $thread, %edx
movl [=11=], %esi
leaq 16(%rsp), %rdi
call pthread_create
leaq 28(%rsp), %rcx
movl $thread, %edx
movl [=11=], %esi
leaq 8(%rsp), %rdi
call pthread_create
movl [=11=], %esi
movq 16(%rsp), %rdi
call pthread_join
movl [=11=], %esi
movq 8(%rsp), %rdi
call pthread_join
movl 28(%rsp), %eax
addl %eax, %eax
movl cnt(%rip), %edx
cmpl %edx, %eax
je .L6
movl cnt(%rip), %esi
movl $.LC1, %edi
movl [=11=], %eax
call printf
.L7:
movl [=11=], %edi
call exit
.L6:
movl cnt(%rip), %esi
movl $.LC2, %edi
movl [=11=], %eax
call printf
jmp .L7
.cfi_endproc
.LFE19:
.size main, .-main
.globl cnt
.bss
.align 4
.type cnt, @object
.size cnt, 4
cnt:
.zero 4
.ident "GCC: (GNU) 6.3.0"
.section .note.GNU-stack,"",@progbits
所以证实了书上的错误