Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # define a set of numbers in the data section of the exe.
- # 4 byte unsigned integer array.
- static a_list_of_numbers: ui32[] = {
- 0x4a, 0x23, 0x0f, 0x41, 0x3e,
- 0x28, 0x1a, 0x61, 0x16, 0x3c,
- 0x0d, 0x1e, 0x37, 0x5d, 0x10,
- 0x54, 0x17, 0x27, 0x10, 0x3e,
- 0x19, 0x3b, 0x0c, 0x45, 0x30,
- 0x19, 0x61, 0x49, 0x3b, 0x0a,
- 0x06, 0x54, 0x32, 0x02, 0x4a,
- 0x0e, 0x61, 0x35, 0x0c, 0x3b,
- 0x26, 0x0e, 0x2a, 0x1b, 0x5e,
- 0x37, 0x40, 0x14, 0x29, 0x0f,
- 0x56, 0x47, 0x23, 0x3a, 0x27,
- 0x15, 0x53, 0x21, 0x4a, 0x07,
- 0x4e, 0x5f, 0x20, 0x13, 0x07,
- 0x40, 0x4d, 0x24, 0x14, 0x51,
- 0x28, 0x39, 0x27, 0x56, 0x34,
- 0x10, 0x0a, 0x03, 0x15, 0x1b,
- 0x52, 0x2b, 0x62, 0x2a, 0x2f,
- 0x0b, 0x37, 0x27, 0x14, 0x58,
- 0x2b, 0x0a, 0x58, 0x01, 0x10,
- 0x35, 0x1e, 0x2e, 0x61, 0x12,
- }
- # this is the entry point. things that are defined can be addressed
- # via a pathing scheme similar to file systems. './' starts at the
- # local group, '~/' starts at the root. main here is the interface
- # definition (standard C main interface in this case). 'x86-64' here
- # specifies which instruction set and required extensions are being used.
- procedure start: ./libc/main x86-64 {
- # this block of register definitions is bound to the scope it
- # is declared in (this case it is the implicit procedure root).
- # these registers are 'mapped' and 'unmapped' at the start and
- # end of the scope (can also be done manually).
- registers {
- accumulator: ui32
- t0: to ui32
- }
- # here we compute the address to pass to sum_ui32. the 'at' syntax
- # can be seen as a dereferencing operator, or the '[reg]' syntax in
- # traditional assemblers. An 'at' chases a pointer type, which is
- # specified using a matching 'to' in the format declaration. A 'to'
- # is implicit when accessing statics.
- lea t0, at ./a_list_of_numbers
- # this call expands to a bit more than just the x86 call instruction.
- # using the interface specified, the stack and register swapping is
- # done automatically.
- invoke ./my_cool_math_lib/sum_ui32 with
- accumulator = accumulator,
- nums = t0,
- num_count = ./a_list_of_numbers.%element_count
- # set the return parameter specified by the 'main' interface. the 'as'
- # syntax here is similar to a cast but does not result in any actual
- # conversion. this is purely to satisfy the format matcher.
- mov return, accumulator as si32
- }
- # simple namespacing for top level definitions.
- push_group my_cool_math_lib
- # the 'auto' here specifies no explicit interface. the interface is instead
- # defined automatically by the parameters specified in the body.
- procedure sum_ui32: auto x86-64 {
- parameters {
- accumulator: ui32
- nums: to ui32
- nums_count: ui32
- }
- registers {
- nums_cur: to ui32
- nums_end: to ui32
- }
- # the second operand here is an expression which evals to a 0
- # immediate in the instruction.
- mov accumulator, ui32(0)
- # get some bounds for the iteration. the correct instruction variant
- # is chosen based on the operand formats.
- mov nums_cur, nums
- mov nums_end, nums_count
- mul nums_end, ui32(8)
- add nums_end, nums_cur
- # this opens a new scope where registers and a new stack frame can be
- # defined (don't do either here since we only use this to jump).
- # %start and %end are defined to be jump targets for branching.
- scope {
- add accumulator, at nums_cur
- add nums_cur, ui32(8)
- cmp nums_cur, nums_end
- jmp<ne> %start
- }
- # note there is no return here. the accumulator parameter is 'persistent'
- # in the default calling convention. in and out parameters are also possible
- # to construct a more c-like calling convention.
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement