기본 콘텐츠로 건너뛰기

C언어 register 변수의 함정카드


C언어를 하다보면 register 라는 CPU의 레지스터에 자료를 저장하는 변수를 알수있다.
대신에 한 프로그램에서 최대 2개 정도까지만 사용이 가능하고 지역변수만 가능 및 32bit CPU는 32bit 크기의 변수만 사용 가능하다.

장점만 보면 기본적으로 메모리쪽에 저장되는 일반 변수들보다 더 빠르게 접근이 가능할 것 같은데...인라인 어셈이랑 메모리랑 레지스터랑 비교하면 어떤게 가장 빠른지 궁금해서 한번 테스트 해보게 되었다.

우선 테스트 해볼 코드는 다음과 같다.

거의 동일한 연산을 하고 다른 점이 있다면 인라인 어셈은 전부 다 레지스터를 이용해서 연산한다는 정도...?

위의 코드를 컴파일 해서 실제로 돌려보면 실행 결과는 다음과 같이 나온다.

!?
그냥 아무런 형식도 지정해주지 않은 auto와 똑같은 결과가 나온다.
# C언어는 기본적으로 아무런 형식을 지정해주지 않으면 auto로 해준다.
# int a => auto int a

그래서 어째서 저런 결과가 나왔는지 컴파일에 옵션을 줘서 어셈파일을 분석해 보았다.


인라인 어셈 auto for
register for
push ebp
mov ebp, esp
mov ecx, 0
jmp SHORT $INLoop$3

$INLoop$3:
cmp ecx, 10000000
jae SHORT $EXIT$4
mov eax, ecx
shl eax, 2
inc ecx
jmp SHORT $INLoop$3

$EXIT$4:
cmp ebp, esp
call __RTC_CheckEsp
popebp
ret,0
push ebp
mov ebp, esp
sub esp, 8
mov DWORD PTR [ebp-8], -858993460
mov DWORD PTR [ebp-4], -858993460
mov DWORD PTR _i$2[ebp], 0
jmp SHORT $LN4@For

$LN2@For:
mov eax, DWORD PTR _i$2[ebp]
add eax, 1
mov DWORD PTR _i$2[ebp], eax

$LN4@For:
cmp DWORD PTR _i$2[ebp], 10000000
jae SHORT $LN1@For
mov ecx, DWORD PTR _i$2[ebp]
shl ecx, 2
mov DWORD PTR _a$1[ebp], ecx
jmp SHORT $LN2@For

$LN1@For:
mov esp, ebp
pop ebp
ret 0
push ebp
mov ebp, esp
sub esp, 8
mov DWORD PTR [ebp-8], -858993460
mov DWORD PTR [ebp-4], -858993460
mov DWORD PTR _i$2[ebp], 0
jmp SHORT $LN4@registeFor

$LN2@registeFor:
mov eax, DWORD PTR _i$2[ebp]
add eax, 1,
mov DWORD PTR _i$2[ebp], eax

$LN4@registeFor:
cmp DWORD PTR _i$2[ebp], 10000000
jae SHORT $LN1@registeFor
mov ecx, DWORD PTR _i$2[ebp]
shl ecx, 2
mov DWORD PTR _a$1[ebp], ecx
jmp SHORT $LN2@registeFor

$LN1@registeFor:
mov esp, ebp
pop ebp
ret 0

함수부분만 잘라서 보면 위와 같은 어셈코드로 변환됐는데, 기본값이랑 register로 한 코드가 차이가 없다. 그리고 register을 적용을 하엿음에도 불구하고 어셈 코드를 보면 메모리를 사용한다. 이게 어찌된 일인걸까?
혹시 64bit가 아니여서 그런가 해서 컴파일을 x64로 바꾸고 long, long long으로도 해보앗지만 동일한 결과가 나왔다.

컴파일러의 문제인지...문제점이 어떤 것인지는 모르지만 적어도 내가 쓰는 Visual studio 2015에서는 저런 결과가 나온다...

얻은 결론)

  • VS 2015에서는 register로 선언해도 실제로는 선언이 않된다.
  • 어려운 작업이 아니고, 굳이 빨리 처리해야된다면 인라인 어셈을 쓰자


Ps. 만약 저랑 같은 VS2015에서 되는분이 있으면 좀 알려주세요... 저만 그런지 궁금하네요;

댓글

이 블로그의 인기 게시물

Android Auto Naver Login (네이버 자동 로그인) - 1

# CAUTION # 시작하기 전에 이 방식은 약간의 편법 을 이용한 방식이고 안드로이드 4.4 이상 부터 지원하는 것을 알려둔다... (그리고 현재 라이브러리로 만드는 중) 사실 이 내용은 누군가의 부탁을 받아서 만들기 시작한건데, 다 완성도 되고 부탁한 애도 관련 일 다 끝낸거 같으니까 포스팅한다... 안드로이드에서 네이버 로그인을 위해서는 간단하게 네이버 API를 사용해서 로그인 하는 방식이 주로 보편적으로 이용된다. 위와 같은 api들이 있는데 네이버 메일을 파싱하거나 네이버 카페의 글 들을 파싱해야되는경우 API 가 없기 때문에 다른 방식을 사용해서 해야된다. 지금부터 그 과정중 가장 기본이되는 네이버 로그인부터 시작해보도록 한다. https://nid.naver.com/nidlogin.login 에서의 네이버 로그인 과정을 분석해보면 id, pw의 길이를 검사해서 입력햇는지 검사 입력되엇으면 http://static.nid.naver.com/enclogin/keys.nhn 또는 https://nid.naver.com/login/ext/keys.nhn 에 접속해서 랜덤 값을 가져온다 js 에서 RSA 암호화  특정 형식으로 POST 쿠키 받기 간략하게 이러한 과정을 거치는데... 내가 아는 한에서는 안드로이드에서는 js 를 돌릴수는 있지만 C# 처럼 자유롭게(?) 이용하는 것이 힘들다. 그래서 처음 선택한 방안이 HtmlUnit 이라는 것과 Sel..뭔 라이브러리가 있는데 여러개 전부 다 테스트를 해 보았지만 전부 작동이 되지를 않았다... 그래서 그냥 라이브러리 없이 진행하기로 했다. 일단 하는 방식은 간단하게 다음과 같다. 웹뷰를 이용해서 로그인 쿠키유지 엄청 간단하다. 그런데 이러한 의문이 들 수도 있다. Q1. 웹뷰를 쓰면 입력을 수동으로 해야될텐데, 그럼 자동이 아니잖아??? A. 웹뷰 써도 자동으로 할 수 있어! 이제 답을 말하자면 WebView에서 ID와 PW...

Android Auto Naver Login (네이버 자동 로그인) - 2

(1편 부터 이어집니다.) 웹뷰에서 자바 스크립트설정이랑 쿠키도 끝낫으니 이제 요청헤더에 몇몇개의 값을 추가해줘야된다. 나중에 로딩할때         web.loadUrl(NAVER_LOGIN, extraHeaders);   이렇게 포함시켜주면 된다. 일단 요청헤더를 추가하기 위해서 Map<String, String> 형식으로 추가해준다.         Map<String, String> extraHeaders = new HashMap<String, String>();         extraHeaders.put("Referer", Config.HEADER_REFERERURI);         extraHeaders.put("ContentType", Config.HEADER_CONTYPE);         extraHeaders.put("User-Agent", Config.HEADER_UA); 대충 이렇게 설정해주는데 각각의 값은 다음과 같다. (코드에서 Ctrl + C, Ctrl + V라 좀 깁니다...) [Class Config]     public static final String HEADER_CONTYPE = "header_ConType = \"application/x-www-form-urlencoded\";";     public static final String HEADER_UA = "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:48.0) Gecko/...