기본 콘텐츠로 건너뛰기

switch-case-default

switch-case-default switch()/case/default source # include <stdio.h> void f ( int a ) { switch ( a ) { case 0 : printf ( "zero\n" ) ; break ; case 1 : printf ( "one\n" ) ; break ; case 2 : printf ( "two\n" ) ; break ; default : printf ( "something unknown\n" ) ; break ; } } int main ( ) { f ( 2 ) ; } x86 MSVC $SG5332 DB 'zero', 0aH, 00H $SG5334 DB 'one', 0aH, 00H $SG5336 DB 'two', 0aH, 00H $SG5338 DB 'something unknown', 0aH, 00H EXTRN ___acrt_iob_func:PROC EXTRN ___stdio_common_vfprintf:PROC _main PROC push ebp mov ebp, esp push 2 call ?f@@YAXH@Z add esp, 4 xor eax, eax pop ebp ret 0 _main ENDP tv64 = -4 ; size = 4 _a$ = 8

Secure-Coding-C-DCL-3

Secure-Coding-C-DCL-3 C 언어 시큐어코딩 - Declare and Initialization 3 상충되는 Linkage 식별자를 선언하지 않는다. Linkage는 동일한 범위 내에서 여러 영역으로 선언되거나 여러 번 선언된 식별자를 동일한 개체나 함수를 참조하도록 만들 수 있다. 식별자는 externally linked, Internally linked 또는 not llinked로 분류된다. 이 세 종류의 분류는 다음과 같은 특징을 갖는다. External linkage: 프로그램에 속한 모든 편집 단위 및 라이브러리에서 동일한 객체 또는 기능을 나타낸다. 식별자는 링커에서 사용할 수 있다. External Internal linkage: 주어진 번역 단위 내에서 동일한 객체 또는 함수를 나타낸다. linker는 내부 링크가 있는 식별자에 대한 정보가 없다. 따라서 이러한 식별자는 번역 단위 내부에 있다. No linkage: 식별자에 연결이 없는 경우 식별자를 사용하는 추가 선언은 새로운 변수 또는 새로운 유형과 같은 새로운 것을 선언한다. 한 번역 내에서 내부 및 외부 링크로 분류된 식별자의 사용은 정의되지 않은 동작이다. 번역의 단위는 헤더와 함께 소스 파일, 전처리 지시어를 통해 포함된 모든 소스 파일을 포함한다. 다음 표는 단일 변환 단위에서 두 번 선언된 객체에 할당된 연결을 나타낸다. 열은 첫 번째 선언, 행은 재 선언을 의미한다. static (second) no linkage (second) extern (second) static (first) internal Undefined Internal no linkage (first) Undefined No linkage External extern (first) Undefined Undefined External 잘못된 코드 예제 이 예제에서 i2 와 i5

Secure-Coding-C-DCL-2

Secure-Coding-C-DCL-2 C 언어 시큐어코딩 - Declare and Initialization 2 식별자를 사용하기 전에 선언한다. C90 표준은 변수와 함수의 암시적 타이핑을 허용하였으나, C11 표준에는 형식 지정자가 필요하며 암시적 함수 선언을 금지하고 있다. 따라서 기존 레거시 코드 중 일부는 암시적 타이핑을 사용하고 있을 확률이 높다. 일부 컴파일러는 계속해서 지원하고 있지만 이는 호환성을 유지하지 위함이므로 새 코드에서는 사용해서는 안된다. 잘못된 코드 예제 C는 더 이상 선언문에 타입 지정자가 없다는 것을 허용하지 않는다. 이 예제는 형식 지정자를 생략한다. extern foo ; 올바른 코드 예제 이 예제는 형식 지정자가 명시적으로 포함되어 있다. extern int foo ; 잘못된 코드 예제 (암시적 함수 선언) 모든 함수는 호출되기 전에 명시적으로 선언되어야 한다. C90에서 명시적 프로토 타입 없이 함수를 호출하면 컴파일러에서 암시적 선언을 제공했다. 함수 호추이 이루어진 지점에서 표시되지 않으면 C90 호환 플랫폼은 extern int identifier(); 를 암시적으로 선언한다. 이 선언은 함수가 int를 반환할 수 있음을 의미한다. 그러나 현재 C 표준을 따르기 위해서는 프로그래머가 모든 함수를 호출하기전에 명시저긍로 프로토 타입을 작성해야 한다. # include <stddef.h> /* #include <stdlib.h> is missing */ int main ( void ) { for ( size_t i = 0 ; i < 100 ; ++ i ) { /* int malloc() assumed */ char * ptr = ( char * ) malloc ( 0x10000000 ) ; * ptr = 'a' ; } return 0 ;

힘내라 청춘. 20171217

힘내라 청춘. 20171215

진짜 전성기와 청춘의 전성기

전성기, 찬란한 청춘을 그려보면 군대 전역 후 폐기 넘치던 대학 시절이 떠오른다. 무엇이든 할 수 있을 것 같고, 무엇이든 될 수 있을 것 같던 그 자신만만한 열정이 생각만해도 벅차오르게 한다. 떠올리는 것만으로도 벅차오르게 하는 전성기의 그 찬란함은 무엇인가. 정녕 다시 돌아올 수 없는가. 고민 끝에 나는 진짜 전성기와 청춘의 전성기, 이렇게 두 가지에 개념을 나누어 보았다. 20대에 누렸던 그 찬란함은 신이 선물하는 젊음의 산물인 것이다. 그 시절의 지치지 않는 체력, 강인한 집중력, 무모한 추진력 모두 그러한 것이다. 어느 것 하나 내가 직접 만들어낸 것이 있었던 가. 인생의 진면목은 끊임 없는 노력에서 피어나는 값진 성과에 있다고 생각한다. 진짜 전성기는 그렇게 만드는 것이다. 하나 하나 피땀 흘려 성취 해낸 결과들이 자신을 높이 세워주었을 때 비로소 진짜 전성기에 도달하는 것이다. 인생을 돌이켜 보았을 때, 지금이 인생에 전성기였다고 기억할 수 있게 노력한다. 지금은 부족한 한낱 직장인에 불가하지만, 내년은 다르리라 믿어 의심치 않는다.

64bit-passing-param

64bit-passing-param 64 비트 인자 전달 방식 source code # include <stdio.h> int main ( ) { printf ( "a=%d; b=%d; c=%d; d=%d; e=%d; f=%d; g=%d; h=%d; i=%d" , \ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ) ; return 0 ; } 처음 4개의 인자는 RCX, RDX, R8, R9 레지스터를 이용하여 전달하고 나머지 인자는 스택을 통해서 전달하는 데, 컴파일러 별 스택 활용 방식에 차이점이 있는 것을 확인할 수 있다. 효율성을 위해 값이 4바이트로 표현 가능한 경우 x86 환경에서 사용되던 exx 레지스터를 활용한다. MSVC 32bit 환경에서 컴파일 시 인자 전달을 위해 PUSH/POP을 사용했던 것과는 대조적으로 MOV를 이용하여 값을 직접 삽입하는 것을 볼 수 있다. $SG4866 DB 'a=%d; b=%d; c=%d; d=%d; e=%d; f=%d; g=%d; h=%d; i=%d', 00H EXTRN __acrt_iob_func:PROC EXTRN __stdio_common_vfprintf:PROC main PROC sub rsp, 88 ; 00000058H mov DWORD PTR [rsp+72], 9 mov DWORD PTR [rsp+64], 8 mov DWORD PTR [rsp+56], 7 mov DWORD PTR [rsp+48], 6 mov DWORD PTR [rsp+40], 5 mov DWORD PTR [rsp+32], 4 mov r9d, 3