一朝掌握汇编语言,终生理解计算机系统。
--题记
现在计算机发展及其迅速,我们能学可学的东西很多,汇编语言已经不再像以前那样必要,但是底层的东西变化却很慢,学习以下我觉得是不吃亏的,尤其是以后立志走C/C++ 路线的程序员。
一句话:我学的就是情怀!
昨天学妹问我一个问题,很简单。是这样的。
#include<stdio.h> int main(){ char a; short b; scanf("%c",&a); scanf("%d",&b); printf("%c %d \n",a,b); }
为什么这里的a 变量不能打印。 现在我们逐层分析: 相信C语法不错的同学都能看到%d 和 short 不对等,语法不对,确实是这样。 可是为什么这样? 这就需要了解变参函数知识了,变参函数中参数不对等,对很靠近答案了。 但是明明是b错了,但是为什么是a有问题? 我们看看汇编代码:
.file "tt.c"
.section .rodata
.LC0:
.string "%c"
.LC1:
.string "%hd"
.LC2:
.string "%c %d \n"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq $16, %rsp
leaq -1(%rbp), %rax
movq %rax, %rsi
movl $.LC0, %edi
movl $0, %eax
call __isoc99_scanf
leaq -4(%rbp), %rax
movq %rax, %rsi
movl $.LC1, %edi
movl $0, %eax
call __isoc99_scanf
movzwl -4(%rbp), %eax
movswl %ax, %edx
movzbl -1(%rbp), %eax
movsbl %al, %eax
movl %eax, %esi
movl $.LC2, %edi
movl $0, %eax
call printf
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (GNU) 4.9.2 20150212 (Red Hat 4.9.2-6)"
.section .note.GNU-stack,"",@progbits
我们可以看到,edi 寄存器保存的是变参。 当我们使用"%d"接收参数的时候,想当于直接给存放b的寄存器强制放了4字节内容,我们知道程序在运行时是以栈的形式存储变量的,所以4字节的b强行符覆盖到了a.所以变量a 的内容被改变了。