Go Language Learning Notes (Twenty-Nine) Assembly Functions

1. Basic Usage:The function identifier is defined using the TEXT assembly directive, indicating that the instructions starting from this line are defined in the TEXT memory segment. The instructions following the TEXT statement generally correspond to the implementation of the function. However, the TEXT directive itself does not concern whether there are instructions following it. Therefore, the symbols defined by TEXT and LABEL are similar, with the distinction that LABEL is used for jump labels. Essentially, both map an identifier to a memory address.2. Function Definition:TEXT symbol(SB),[flags,] $framesize[-argsize]The function definition consists of five parts: the TEXT directive, the function name, optional flags, the function frame size, and optional parameter size.TEXT is used to define function symbols, and the path of the current package can be omitted in the function name. The name of the function is followed by (SB), indicating that it is the offset of the function name symbol relative to the pseudo-register SB. The combination of the two ultimately results in an absolute address. The names of global variables and global functions, as global identifiers, are generally based on the relative address of the pseudo-register SB. The flags section is used to indicate some special behaviors of the function, with the common NOSPLIT flag mainly used for leaf functions to avoid stack splitting. The framesize part indicates how much stack space is needed for the function’s local variables, which includes implicit stack space prepared for calling parameters when calling other functions. Finally, the optional parameter size can be omitted because the compiler can infer the function’s parameter size from the Go language function declaration.2.1 Go Function:func Swap(a,b int) (int,int)2.2 Assembly Format:TEXT ·Swap(SB),NOSPLIT,$0-32TEXT ·Swap(SB),NOSPLIT,$03. Function Parameters and Return Values:In Go assembly, a pseudo-register FP is introduced, representing the address of the previous frame, which is the address of the first parameter. The parameters a, b, ret0, and ret1 can be referenced using +0(FP), +8(FP), +16(FP), and +24(FP) respectively.In assembly code, parameters cannot be directly used in the form of 0+(FP). Any variable accessed through the pseudo-register FP must be combined with a temporary identifier prefix to be valid.4. Local Variables in Functions:From the perspective of Go language functions, local variables are variables explicitly defined by the function, which also include the function’s parameters and return value variables. However, from the perspective of Go assembly, local variables refer to memory variables corresponding to the current function stack frame during the function’s execution, excluding parameters and return values. The space of the function stack frame mainly consists of the function parameters, return values, local variables, and space for parameters and return values of other called functions.To facilitate access to local variables, Go assembly introduces a pseudo-register SP, corresponding to the bottom of the current stack frame. Since the bottom of the stack in the current stack frame is fixed, local variables are also fixed relative to the pseudo-register SP, simplifying the maintenance of local variables. The distinction between true and pseudo-register SP follows one principle: if there is a temporary identifier prefix when using SP, it is the pseudo-register SP; otherwise, it is the true register SP. For example, a(SP) and b+8(SP) have temporary prefixes a and b, indicating pseudo-register SP, while (SP) and +8(SP) without temporary identifiers indicate true register SP.On the X86 platform, function calls grow from high addresses to low addresses, so the pseudo-register SP corresponding to the bottom of the stack frame actually corresponds to a larger address. The top of the current stack corresponds to the real existing register SP, which corresponds to the top of the current function’s stack, corresponding to a smaller memory address. If the entire memory is represented by a Memory array, then Memory[0(SP):end-0(SP)] corresponds to the slice of the current stack frame, where the starting position is the true register SP and the ending position is the tail register SP. The true register SP is generally used to represent parameters and return values of other functions, corresponding to lower memory addresses, so the offset of accessed variables is an integer. The pseudo-register SP corresponds to higher addresses, and the corresponding local variables are negative.4.1 Go Function:func Foo(){var c []bytevar b int16var a bool}4.2 Go Assembly:TEXT ·Foo(SB),$32-0MOVQ a-32(SP),AXMOVQ b-30(SP),BXMOVQ c_data-24(SP),CXMOVQ c_len-16(SP),DXMOVQ c_cap(SP),DIRETThe Foo function has three local variables but does not call other functions. Due to alignment and padding issues, the size of the function’s stack frame is 32 bytes. Since the Foo function has no parameters and return values, the size of parameters and return values is 0 bytes.May you be blessed in your pursuit of knowledge.

Leave a Comment