Search code examples
assemblyx86computer-sciencex86-64

What does this x86-64 addq instruction mean, which only have one operand? (From CSAPP book 3rd Edition)


In the following instructions, how does the addq work? It only has one operand, the book claims that it increments %rdx, but %rdx is not in this instruction. I am so confused...

This is from the book Computer Systems A Programmers Perspective, 3rd Edition.

enter image description here

enter image description here

enter image description here


Solution

  • As @Jester pointed out in the comment. It is indeed an error. I actually typed in the program and compiled it using gcc on linux. Below is the results.

    C program: 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;
    }
    

    Compile using gcc 6.3.0

    $ gcc -pthread -Og -S badcnt.c

    Below is the contents in badcnt.s

            .file   "badcnt.c"
            .text
            .globl  thread
            .type   thread, @function
    thread:
    .LFB20:
            .cfi_startproc
            movl    (%rdi), %ecx
            movl    $0, %edx
            jmp     .L2
    .L3:
            movl    cnt(%rip), %eax
            addl    $1, %eax
            movl    %eax, cnt(%rip)
            addl    $1, %edx
    .L2:
            cmpl    %ecx, %edx
            jl      .L3
            movl    $0, %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    $40, %rsp
            .cfi_def_cfa_offset 48
            cmpl    $2, %edi
            je      .L5
            movq    (%rsi), %rsi
            movl    $.LC0, %edi
            movl    $0, %eax
            call    printf
            movl    $0, %edi
            call    exit
    .L5:
            movq    8(%rsi), %rdi
            movl    $10, %edx
            movl    $0, %esi
            call    strtol
            movl    %eax, 28(%rsp)
            leaq    28(%rsp), %rcx
            movl    $thread, %edx
            movl    $0, %esi
            leaq    16(%rsp), %rdi
            call    pthread_create
            leaq    28(%rsp), %rcx
            movl    $thread, %edx
            movl    $0, %esi
            leaq    8(%rsp), %rdi
            call    pthread_create
            movl    $0, %esi
            movq    16(%rsp), %rdi
            call    pthread_join
            movl    $0, %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    $0, %eax
            call    printf
    .L7:
            movl    $0, %edi
            call    exit
    .L6:
            movl    cnt(%rip), %esi
            movl    $.LC2, %edi
            movl    $0, %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
    

    So it confirms the mistake of the book.