성태의 닷넷 이야기
홈 주인
모아 놓은 자료
프로그래밍
질문/답변
사용자 관리
사용자
메뉴
아티클
외부 아티클
유용한 코드
온라인 기능
MathJax 입력기
최근 덧글
[정성태] Working with Rust Libraries from C#...
[정성태] Detecting blocking calls using asyn...
[정성태] 아쉽게도, 커뮤니티는 아니고 개인 블로그입니다. ^^
[정성태] 질문이 잘 이해가 안 됩니다. 우선, 해당 소스코드에서 ILis...
[양승조
] var대신 dinamic으로 선언해서 해결은 했습니다. 맞는 해...
[양승조
] 또 막혔습니다. ㅠㅠ var list = props[i].Ge...
[양승조
] 아. 감사합니다. 어제는 안됐던것 같은데....정신을 차려야겠네...
[정성태] "props[i].GetValue(props[i])" 코드에서 ...
[정성태] 저렇게 조각 코드 말고, 실제로 재현이 되는 예제 프로젝트를 압...
[정성태] Modules 창(Ctrl+Shift+U)을 띄워서, 해당 Op...
글쓰기
제목
이름
암호
전자우편
HTML
홈페이지
유형
제니퍼 .NET
닷넷
COM 개체 관련
스크립트
VC++
VS.NET IDE
Windows
Team Foundation Server
디버깅 기술
오류 유형
개발 환경 구성
웹
기타
Linux
Java
DDK
Math
Phone
Graphics
사물인터넷
부모글 보이기/감추기
내용
<div style='display: inline'> <h1 style='font-family: Malgun Gothic, Consolas; font-size: 20pt; color: #006699; text-align: center; font-weight: bold'>geek스러운 C/C++ 퀴즈 문제</h1> <p> 아래의 문제를 보게 되었는데요. ^^<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > 진짜 어려운 프로그래밍 퀴즈 문제 ; <a target='tab' href='https://www.okjsp.net/seq/215850'>https://www.okjsp.net/seq/215850</a> </pre> <br /> 문제를 여기다 복사해 보면 다음과 같습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > typedef int (*f)(); int variable = 1; int function() { if (variable == 1) return /* INPUT */ <------ put your solution here! 5; victory(); } int main() { function(); return 0; } // your main objective is to call the victory function. // you must put one line of your code: // - max 11 chars. // - you can't use: "main", "victory", "asm", "%", "*", "_", "#", "/", """, "'". // - you have only one semicolon. </pre> <br /> 어렵군요. ^^ 저도 풀기는 했지만 11자 제한은 넘어버려서 16자로 맞췄습니다. 게다가 좀 일반적이지도 않고!<br /> <br /> 제가 한 방법은 다음과 같습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > int function() { if (variable == 1) return (function+25)(); 5; victory(); } </pre> <br /> 이 코드는 Visual C++에서는 함수 포인터 연산이 자유롭지 않아서 컴파일이 안되고 대신 gcc에서 해야 합니다. 그런데, 왜 25바이트를 더했냐고요? ^^<br /> <br /> 일단, 숫자 25대신 아무 거나 대입시켜서 위의 코드를 컴파일 해야 하는데요. 이 때 어셈블리 코드를 출력시켜 주어야 합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > How to get GCC to generate assembly code ; <a target='tab' href='http://www.delorie.com/djgpp/v2faq/faq8_20.html'>http://www.delorie.com/djgpp/v2faq/faq8_20.html</a> </pre> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > gcc -c -g -Wa,-a,-ad ConsoleApplication1.c > foo.lst </pre> <br /> 출력된 어셈블리 코드에서 _function 부분만 발췌해 보면 다음과 같은 코드를 볼 수 있는데,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > 40 0000 01000000 .long 1 41 .text 42 .globl _function 44 _function: 45 LFB7: 13:ConsoleApplication1.c **** 14:ConsoleApplication1.c **** typedef int (*f)(); 15:ConsoleApplication1.c **** int variable = 1; 16:ConsoleApplication1.c **** <span style='color: blue; font-weight: bold'> 17:ConsoleApplication1.c **** int function() 18:ConsoleApplication1.c **** { 46 .loc 1 18 0 47 .cfi_startproc 48 0019 55 pushl %ebp</span> 49 LCFI3: 50 .cfi_def_cfa_offset 8 51 .cfi_offset 5, -8 52 001a 89E5 movl %esp, %ebp 53 LCFI4: 54 .cfi_def_cfa_register 5 55 001c 83EC08 subl $8, %esp 19:ConsoleApplication1.c **** if (variable == 1) 56 .loc 1 19 0 57 001f A1000000 movl _variable, %eax 57 00 58 0024 83F801 cmpl $1, %eax 59 0027 7509 jne L3 20:ConsoleApplication1.c **** return (function+25)(); 60 .loc 1 20 0 61 0029 B8320000 movl $_function+25, %eax 61 00 62 002e FFD0 call *%eax 63 0030 EB05 jmp L2 64 L3: <span style='color: blue; font-weight: bold'> 21:ConsoleApplication1.c **** 22:ConsoleApplication1.c **** 5; 23:ConsoleApplication1.c **** victory(); 65 .loc 1 23 0 66 0032 E8C9FFFF call _victory</span> 66 FF 67 L2: 24:ConsoleApplication1.c **** } </pre> <br /> 이 중에서, function 함수 포인터의 진입점에서 call _victory 기계어 코드까지 출력된 바이트 수를 합산해 보면,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > 55 (1 byte) 89E5 (2 bytes) 83EC08 (3 bytes) A1000000 (4 bytes) 00 (1 byte) 83F801 (3 bytes) 7509 (2 bytes) B8320000 (4 bytes) 00 (1 byte) FFD0 (2 bytes) EB05 (2 bytes) ==================== 25 bytes </pre> <br /> 정확히 25바이트가 나옵니다. 따라서, return (function+25)();는 25바이트 옵셋 후의 코드를 진입점으로 하는 함수를 호출하는 것과 같은 효과를 가지는 것입니다.<br /> <br /> 테스트를 위해 코드를 다음과 같이 바꿔 볼까요?<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > #include <stdio.h> void victory() { printf("victory2 called!!!"); } typedef int (*f)(); int variable = 1; int function() { if (variable == 1) return (function+25)(); 5; victory(); } int main() { function(); return 0; } </pre> <br /> 이제 gcc로 컴파일하고 실행하면 "victory2 called!!!" 문자열이 출력되는 것을 확인할 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > $ gcc ConsoleApplication1.c $ a victory2 called!!! </pre> <br /> 물론, 이 방법을 사용하면 Debug/Release 빌드마다 옵셋이 바뀐다는 문제점이 있긴 합니다. 어쨌든, 저는 최소한의 문자열로 축소하기 위해 써 먹은 방법이 여기까지입니다.<br /> <br /> 어떻게 하면 5자를 더 줄일 수 있을까요? ^^ 함수 포인터 타입 f와 "5;" 로 끝나는 코드를 잘 이용하는 것이 문제 출제자의 의도 같은데...<br /> </p><br /> <br /><hr /><span style='color: Maroon'>[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]</span> </div>
첨부파일
스팸 방지용 인증 번호
1448
(왼쪽의 숫자를 입력해야 합니다.)