jasmin ¶
- assembler for java vm
- jasmin에서 사용하는 바이트코드로 된 .j(jasmin assembly) 파일을 .class(JVM bytecode) 파일로 만들어주는 역할.
- JVM에서 공식 어셈블리 포맷을 공개한 것이 없기 때문.
- JVM에서 공식 어셈블리 포맷을 공개한 것이 없기 때문.
- .class 에서 .j를 만들어주는 classfileanalyzer 라는 것도 있음.
ClassFileAnalyzer ¶
- .java --( javac ) --> .class
- .j --(classFileAnalyzer/jasper/..) --> .class
- classFileAnalyzer에 .class을 줘서 실행하면 assembly code가 생성됨
왜 jasmin을 쓰는가? ¶
- 컴파일러를 만든다고 했을 때 실제로 high level언어에서 머신코드까지 만드는 경우는 별로 없음.
- 머신코드를 생성하는 부분은 해당 기기에 의존하는 부분이 있기 때문에 실제로는 어셈블리까지 만들고 그 이후에 머신코드를 만드는 부분은 따로 만든다고 함.
javap ¶
- java의 .class 파일을 역어셈블 하는 프로그램. 콘솔에서 사용 (prints java's descriptions)
javap JavapTest.class // signature 만 표시됨. 실제 내용은 안나오고 선언만. javap -c JavapTest.class // 실제 .class파일의 내용이 바이트 코드 수준으로 표시됨.
translate와 compile의 차이 ¶
- high level에서 high level로 변환하는 것은 일반적으로 translate
- high level에서 low level로 변환하는 것을 주로 compile이라고 말함.
- high level과 low level의 차이는 실제 머신에서 수행될 형태인가 아닌가의 여부.
GCC Verbose ¶
- gcc의 -v 옵션
gcc -v VerboseTest.c -o VerboseTest // 와 같은 형태로 콘솔에서 실행
- 실행 시 리눅스 기준으로 COLLECT_GCC_OPTIONS에 /tmp/ccIVwQV1.s 와 같은 형태로 .s 파일을 생성하는 것을 볼 수 있음.
- 해당 .s파일을 출력해보면 어셈블러 코드가 출력됨.
- .c -> FE -> BE -> assembly file -> assembler -> machine code 에서 assembly file의 생성까지가 cc의 역할. 이후 .s를 .o로 만드는 것이 어셈블러가 하는 역할. 윈도우에서는 윈도우에 맞는 머신코드를 만들기 위한 다른 어셈블러가 실행됨.
// mac에서 수행시. /usr/llvm-gcc-4.2/bin/../libexec/gcc/i686-apple-darwin11/4.2.1/cc1plus -quiet -v -imultilib x86_64 -iprefix /usr/llvm-gcc-4.2/bin/../lib/gcc/i686-apple-darwin11/4.2.1/ -D__DYNAMIC__ nca.cpp -fPIC -quiet -dumpbase nca.cpp -mmacosx-version-min=10.8.5 -m64 -mtune=core2 -auxbase nca -version -D__private_extern__=extern -o /var/folders/zn/v_hqwzws1nx4l19qsdz86xn80000gn/T//ccGprRXs.s
- .s 파일은 assembly 파일
/var/folders/zn/v_hqwzws1nx4l19qsdz86xn80000gn/T//ccGprRXs.s
- s파일로 다시 o 파일을 만듦
/usr/llvm-gcc-4.2/bin/../libexec/gcc/i686-apple-darwin11/4.2.1/as -arch x86_64 -force_cpusubtype_ALL -o /var/folders/zn/v_hqwzws1nx4l19qsdz86xn80000gn/T//ccrYBpRg.o /var/folders/zn/v_hqwzws1nx4l19qsdz86xn80000gn/T//ccGprRXs.s
java bytecode ¶
mnemonic : 작업 수행, opcode들이 mnemonic
opcode(operator)
operand
- dup : stack의 탑을 스택에 복제,
directive : 지시어, assembler에게 지정하는 명령어, .으로 시작opcode(operator)
operand
- bytecode instruction list (참고)
- new mnemonic과 invokespecial 다른점
- new는 객체를 메모리에 할당,
- invokespecial <init>은 할당된 객체를 초기화
- invokestatic은 this가 필요없다!
- invokespecial VS invokevirtual
- invokespecial은 스택의 top를 파라메터로 받고, 스택의 top에서 두번째를 this(init의 주체)로 쓴다. <- dup를 하는 이유
- 생성자는void return
invokevirtual- 생성자는void return
- 모든 객체의 함수는 invokevirtual
- virtual이란 실행될 함수를 compile 시간에 결정할 수 없고 run time에 결정. (vtable lookup, c는 virtual 함수만 vtable에 기록됨)
invokeinterface- virtual이란 실행될 함수를 compile 시간에 결정할 수 없고 run time에 결정. (vtable lookup, c는 virtual 함수만 vtable에 기록됨)
- 구체 클래스를 this로 받아야함
- 레퍼런스 타입 (참고)
- 스택에 객체의 주소가 들어있음. premitive 변수가 아니면 전부 레퍼런스 타입
- 메서드의 위치를 나타낼때는 java/io/InputStream/read 이런식으로.
- jvm의 data type
int[] : [I
String : Ljava/lang/string;
String[][] : [[Ljava/lang/string;
- jvm의 함수
() 괄호안에 파라메터
astore_# <- 코드에 선언된 #번째 지역변수에 저장.
aload_# <- 코드에 선언된 #번째 지역변수에 저장된 값을 가져옴.
aload_# <- 코드에 선언된 #번째 지역변수에 저장된 값을 가져옴.
* (1+2)*3.1을 jasmin assembly로 나타내면
getstatic java/lang/system/out Ljava/io/printstream; iconst_1 iconst_2 iadd i2d ldc 3.1 dmul invokevirtual java/io/printstream/print(D)V return