⬆️ ⬇️

Writing Hello World on FASM

One languid Friday evening got a crazy idea in my head: why don't I think up my brain and write HelloWorld in assembler. However, it seemed too simple. And let's not build the x86 program, but the java class? No sooner said than done.



First we find the JVM specification . As we can see, the Java class file consists of:





In Java, the order is big endian, while FASM is an assembler under x86, where little endian is adopted, so we will immediately write macros to convert numbers from one order to another:



u1 equ db ; u1 - 1 ,   macro u2 [data] { ; u2 - 2  forward ;       ,  u2 0x1234, 0x5678 ;       u1 (((data) shr 8) and 0xFF) ;    u1 ((data) and 0xFF) ;   } macro u4 [data] { ; u4 - 4 ,    u2 forward u2 (((data) shr 16) and 0xFFFF) u2 ((data) and 0xFFFF) } 


In general, the macro language FASM is so powerful that you can write another language in it, and not in one way.

')

A constant pool is quite intricate, one descriptor refers to another, it is the third, but you can figure it out - it's all the same people wrote.



Elements of the constant pool in the general case look like this:



 cp_info { u1 tag; u1 info[]; } 


A full list of tags is given in the documentation, I will not describe them in detail. I will describe the trick that I used to automatically calculate the size of the pool (as well as methods, fields, etc.).



The construction of the form const # name - sticks together the text const and the value from the constant name. The construction is similar to that of the C macros.



 const_count = 0 macro const name* { ;   const_#name: const_count = const_count + 1 name = const_count ;   (FASM )      } 


Although in FASM terminology, constants are called constants, in fact they behave as variables, and many manipulations can be made with them.



Then we declare macros for the beginning and for the end:



 macro ConstantPool { u2 const_count_end + 1 ;      ; +1   0   ,     } 


But after all such variable does not exist, you will tell. And you will be right. Does not exist yet. FASM is a multi-pass assembler, and what was not found on the first pass, it will remember and connect on the second or further.

 macro ConstantPoolEnd { UTF8 code_attr, 'Code' const_count_end = const_count ;      . } 


On the next pass, the assembler will substitute for const_count_end exactly as much as he counted constants.



Methods and fields are organized in a similar way. I will give an example of a macro that generates a constant Method



 macro UTF8 name, text { const name u1 1 ; tag u2 .end - .start .start: u1 text .end: } macro Class name, className { UTF8 className_#name, className const name u1 7 ; tag u2 className_#name } macro NameAndType name, nameText, typeText { UTF8 name_#name, nameText UTF8 type_#name, typeText const name u1 12 ; tag u2 name_#name u2 type_#name } macro Method name, className, methodName, methodType { Class class_#name, className ;   Class NameAndType nameAndType_#name, methodName, methodType ;   NameAndType const name u1 10 ; tag u2 class_#name u2 nameAndType_#name } 


Here you can see how the links go - Method refers to Class, Class refers to UTF8, also with NameAndType. Arguments are passed to the macro as strings, for example, Method printlnInt, 'java/io/PrintStream', 'println', '(I)V' .



And finally, the source itself:



 format binary as 'class' include 'java.inc' ; --- FILE --- magic: u4 0xCAFEBABE version: u4 51 ConstantPool Class this, 'java' Class super, 'java/lang/Object' UTF8 main, 'main' UTF8 main_sig, '([Ljava/lang/String;)V' Field o, 'java/lang/System', 'out', 'Ljava/io/PrintStream;' Method println, 'java/io/PrintStream', 'println', '(Ljava/lang/String;)V' Method printlnInt, 'java/io/PrintStream', 'println', '(I)V' String hello, 'Hello World!' ConstantPoolEnd u2 PUBLIC, this, super, 0, 0 ;  ,  ,    Methods MethodStart PUBLIC or STATIC, main, main_sig, 2, 1 getstatic o ldc hello ;   ,   invokevirtual println getstatic o bipush 42 invokevirtual printlnInt return MethodEnd MethodsEnd u2 0 ;   


»The full code can be viewed here .



Thanks for attention!

Source: https://habr.com/ru/post/309922/



All Articles