good design of C code & its relative assembly code
看到很overwhelming,快吐血時突然發現自己終於又看完一課,
把看完後該課最好的code design範例貼上, 因為真的太棒了:
#include <cs50.h>
#include <stdio.h>
void cough(int n);
void say(string s, int n);
void sneeze(int n);
int main(void)
{
cough(3);
sneeze(3);
}
void cough(int n)
{
say("cough", n);
}
void sneeze(int n)
{
say("achoo", n);
}
void say(string s, int n)
{
for (int i = 0; i < n; i++) {
printf("%s\n", s);
}
}
p.s. 以上code學習自哈佛線上課程
最後, 想紀錄一個學到的東西, 當有人對我說: 去compile你的C source code吧, 實際上包含以下步驟:
preprocessing -> compiling -> assembling -> linking
其中, 我想貼的是上述例子若在assembling階段時的從上階段得來的assembly code(檔名: xxx.s)長得樣子如下:
.text
.file "cough.c"
.globl main
.align 16, 0x90
.type main,@function
main: # @main
.cfi_startproc
# BB#0:
pushq %rbp
.Ltmp0:
.cfi_def_cfa_offset 16
.Ltmp1:
.cfi_offset %rbp, -16
movq %rsp, %rbp
.Ltmp2:
.cfi_def_cfa_register %rbp
movl $3, %edi
callq cough
movl $3, %edi
callq sneeze
xorl %eax, %eax
popq %rbp
retq
.Ltmp3:
.size main, .Ltmp3-main
.cfi_endproc
.globl cough
.align 16, 0x90
.type cough,@function
cough: # @cough
.cfi_startproc
# BB#0:
pushq %rbp
.Ltmp4:
.cfi_def_cfa_offset 16
.Ltmp5:
.cfi_offset %rbp, -16
movq %rsp, %rbp
.Ltmp6:
.cfi_def_cfa_register %rbp
subq $16, %rsp
movabsq $.L.str, %rax
movl %edi, -4(%rbp)
movl -4(%rbp), %esi
movq %rax, %rdi
callq say
addq $16, %rsp
popq %rbp
retq
.Ltmp7:
.size cough, .Ltmp7-cough
.cfi_endproc
.globl sneeze
.align 16, 0x90
.type sneeze,@function
sneeze: # @sneeze
.cfi_startproc
# BB#0:
pushq %rbp
.Ltmp8:
.cfi_def_cfa_offset 16
.Ltmp9:
.cfi_offset %rbp, -16
movq %rsp, %rbp
.Ltmp10:
.cfi_def_cfa_register %rbp
subq $16, %rsp
movabsq $.L.str1, %rax
movl %edi, -4(%rbp)
movl -4(%rbp), %esi
movq %rax, %rdi
callq say
addq $16, %rsp
popq %rbp
retq
.Ltmp11:
.size sneeze, .Ltmp11-sneeze
.cfi_endproc
.globl say
.align 16, 0x90
.type say,@function
say: # @say
.cfi_startproc
# BB#0:
pushq %rbp
.Ltmp12:
.cfi_def_cfa_offset 16
.Ltmp13:
.cfi_offset %rbp, -16
movq %rsp, %rbp
.Ltmp14:
.cfi_def_cfa_register %rbp
subq $32, %rsp
movq %rdi, -8(%rbp)
movl %esi, -12(%rbp)
movl $0, -16(%rbp)
.LBB3_1: # =>This Inner Loop Header: Depth=1
movl -16(%rbp), %eax
cmpl -12(%rbp), %eax
jge .LBB3_4
# BB#2: # in Loop: Header=BB3_1 Depth=1
movabsq $.L.str2, %rdi
movq -8(%rbp), %rsi
movb $0, %al
callq printf
movl %eax, -20(%rbp) # 4-byte Spill
# BB#3: # in Loop: Header=BB3_1 Depth=1
movl -16(%rbp), %eax
addl $1, %eax
movl %eax, -16(%rbp)
jmp .LBB3_1
.LBB3_4:
addq $32, %rsp
popq %rbp
retq
.Ltmp15:
.size say, .Ltmp15-say
.cfi_endproc
.type .L.str,@object # @.str
.section .rodata.str1.1,"aMS",@progbits,1
.L.str:
.asciz "cough"
.size .L.str, 6
.type .L.str1,@object # @.str1
.L.str1:
.asciz "achoo"
.size .L.str1, 6
.type .L.str2,@object # @.str2
.L.str2:
.asciz "%s\n"
.size .L.str2, 4
.ident "Ubuntu clang version 3.6.0-2ubuntu1~trusty1 (tags/RELEASE_360/final) (based on LLVM 3.6.0)"
.section ".note.GNU-stack","",@progbits
希望上述的code我不會看懂, 因這是給CPU看懂的instructions, CPU本身有0s和1s的patterns去配對這些instructions。
把看完後該課最好的code design範例貼上, 因為真的太棒了:
#include <cs50.h>
#include <stdio.h>
void cough(int n);
void say(string s, int n);
void sneeze(int n);
int main(void)
{
cough(3);
sneeze(3);
}
void cough(int n)
{
say("cough", n);
}
void sneeze(int n)
{
say("achoo", n);
}
void say(string s, int n)
{
for (int i = 0; i < n; i++) {
printf("%s\n", s);
}
}
p.s. 以上code學習自哈佛線上課程
最後, 想紀錄一個學到的東西, 當有人對我說: 去compile你的C source code吧, 實際上包含以下步驟:
preprocessing -> compiling -> assembling -> linking
其中, 我想貼的是上述例子若在assembling階段時的從上階段得來的assembly code(檔名: xxx.s)長得樣子如下:
.text
.file "cough.c"
.globl main
.align 16, 0x90
.type main,@function
main: # @main
.cfi_startproc
# BB#0:
pushq %rbp
.Ltmp0:
.cfi_def_cfa_offset 16
.Ltmp1:
.cfi_offset %rbp, -16
movq %rsp, %rbp
.Ltmp2:
.cfi_def_cfa_register %rbp
movl $3, %edi
callq cough
movl $3, %edi
callq sneeze
xorl %eax, %eax
popq %rbp
retq
.Ltmp3:
.size main, .Ltmp3-main
.cfi_endproc
.globl cough
.align 16, 0x90
.type cough,@function
cough: # @cough
.cfi_startproc
# BB#0:
pushq %rbp
.Ltmp4:
.cfi_def_cfa_offset 16
.Ltmp5:
.cfi_offset %rbp, -16
movq %rsp, %rbp
.Ltmp6:
.cfi_def_cfa_register %rbp
subq $16, %rsp
movabsq $.L.str, %rax
movl %edi, -4(%rbp)
movl -4(%rbp), %esi
movq %rax, %rdi
callq say
addq $16, %rsp
popq %rbp
retq
.Ltmp7:
.size cough, .Ltmp7-cough
.cfi_endproc
.globl sneeze
.align 16, 0x90
.type sneeze,@function
sneeze: # @sneeze
.cfi_startproc
# BB#0:
pushq %rbp
.Ltmp8:
.cfi_def_cfa_offset 16
.Ltmp9:
.cfi_offset %rbp, -16
movq %rsp, %rbp
.Ltmp10:
.cfi_def_cfa_register %rbp
subq $16, %rsp
movabsq $.L.str1, %rax
movl %edi, -4(%rbp)
movl -4(%rbp), %esi
movq %rax, %rdi
callq say
addq $16, %rsp
popq %rbp
retq
.Ltmp11:
.size sneeze, .Ltmp11-sneeze
.cfi_endproc
.globl say
.align 16, 0x90
.type say,@function
say: # @say
.cfi_startproc
# BB#0:
pushq %rbp
.Ltmp12:
.cfi_def_cfa_offset 16
.Ltmp13:
.cfi_offset %rbp, -16
movq %rsp, %rbp
.Ltmp14:
.cfi_def_cfa_register %rbp
subq $32, %rsp
movq %rdi, -8(%rbp)
movl %esi, -12(%rbp)
movl $0, -16(%rbp)
.LBB3_1: # =>This Inner Loop Header: Depth=1
movl -16(%rbp), %eax
cmpl -12(%rbp), %eax
jge .LBB3_4
# BB#2: # in Loop: Header=BB3_1 Depth=1
movabsq $.L.str2, %rdi
movq -8(%rbp), %rsi
movb $0, %al
callq printf
movl %eax, -20(%rbp) # 4-byte Spill
# BB#3: # in Loop: Header=BB3_1 Depth=1
movl -16(%rbp), %eax
addl $1, %eax
movl %eax, -16(%rbp)
jmp .LBB3_1
.LBB3_4:
addq $32, %rsp
popq %rbp
retq
.Ltmp15:
.size say, .Ltmp15-say
.cfi_endproc
.type .L.str,@object # @.str
.section .rodata.str1.1,"aMS",@progbits,1
.L.str:
.asciz "cough"
.size .L.str, 6
.type .L.str1,@object # @.str1
.L.str1:
.asciz "achoo"
.size .L.str1, 6
.type .L.str2,@object # @.str2
.L.str2:
.asciz "%s\n"
.size .L.str2, 4
.ident "Ubuntu clang version 3.6.0-2ubuntu1~trusty1 (tags/RELEASE_360/final) (based on LLVM 3.6.0)"
.section ".note.GNU-stack","",@progbits
希望上述的code我不會看懂, 因這是給CPU看懂的instructions, CPU本身有0s和1s的patterns去配對這些instructions。
留言
張貼留言