Assembly Language Standards 1 Introduction Assembly Language code is difficult to understand without documentation. These Assembly Language Standards address function documentation headers documenting instructions Accurate documentation is essential for others to understand code. Additionally, documentation can help explain more obscure functionality which the programmer might forget. 2 Function Documentation Header Each subroutine (function) must be documented with a documentation header: #******************* # Purpose: # # # # # # # # # # # # # # # # # # # # # Name of Function ********************************* Explain what the function does including a brief overview of what it returns. Parameters: (if necessary) List each parameter on a separate line including data type name and description. Each item should begin with whether the parameter is passed in, out or both: I Passed in. Value isn’t modified by subroutine. O Passed out. Value is returned through this parameter. I/O Modified. Original value is used, but this subroutine modifies it. It should then show its offset from the %ebp, its data type, its name, and its meaning. Global Variables: (if necessary) variableName (staticOrExternal)describe its purpose Locals: (if necessary) Describe each automatic variable including its offset in the stack. Notes: Include any special assumptions. If global variables are referenced, reference them. Explain critical parts of the algorithm. Return value: List the values returned by the function. Do not list returned parameters. Remove if void. Example: #******************* hexDump ********************************* # Purpose: # hexDump prints (to stdout) the address of the specified # memory area being dumped, prints the contents of that # memory area in printable characters (where possible) and # hexadecimal, and returns the number of lines processed. # Parameters: # i 8(%ebp) char *psbBuffer this is the address of the memory # area to be dumped. It may contain # printable and binary characters. # i 12(%ebp) int iBufferLength the length of the memory area in bytes. # It must be less than 4800 bytes. # i 16(%ebp) int iBytesPerLine the number of bytes to print per line. # This value must be at least 10 and at # most 40. # Locals: # -4(%ebp) int iLineOffset byte address of the print line # -8(%ebp) int i subscript of the current character # being printed # -12(%ebp) int iNumChars the number of characters printed # on a line. For most lines except # the last one, it is the same as # the iBytesPerLine. # -16(%ebp) int iNullLineCnt count of the number of consecutive # lines which are all zeroes # -20(%ebp) char *pChar Pointer to a character within the # buffer. # Notes: # 1. The dump output is broken into many lines based on # iBufferLength and iBytesPerLine. For example, if # the buffer is 200 bytes and the iBytesPerLine is # 10 bytes/line, it will logically print 20 lines. # 2. Each printed line includes its beginning offset (relative # to 0). # 3. If a line or multiple lines of output would have been # all zeroes, it is suppressed. A message is printed # stating how many lines were suppressed. # 4. The output is written to stdout. # Return value: # -1 invalid parameter # n number of lines printed including suppressed lines 3 Documenting Instructions This is much more difficult to document than C programs. We have several considerations: Documentation on the instruction Documentation about register usage Explain conditionals Explain obscure instructions 3.1 Documentation on Instructions Within the code, document what each instruction is doing based on your global, local, and parameter names. If a register (e.g., is holding one of those, the documentation should make that clear. Example: movl 16(%ebp), %edx # iBytesPerLine -> %edx addl %edx, -4(%ebp) # Add iBytesPerLine to iLineOffset 3.2 Register Usage Explain how registers are used. If a register is mostly used for a particular purpose, explain (other than calling convention registers like %ebp and %esp) what it does. Example: # # # # # 3.3 Register Usage: %ebx for pChar (the pointer into the buffer) %ecx for i (subscript into the buffer) Conditionals Provide comments which explain what is happening with conditionals. For an if-then-else, document the true and false (else) parts. Example: # # check iGradePt > 0 # testl %eax, %eax jle .LFALSE4 # # true: iGradePt > 0 # addl $1, iPass jmp .LAFTER4 # # false: iGradePt <= 0 # .LFALSE4: addl $1, iFail .LAFTER4: 3.4 # test iGradePt # if iGradePt <= 0, jmp to .LFALSE4 # iPass++ # Jump over false part # iFail++ Obscure Code Explain obscure code. Example: # # # # # # # # determine the address of the szStudentId[i] since each element is 20 bytes long, we need to multiply the subscript by 20. using leal (x,x,4) will multiply register x by 5 using leal (,x,4) will multiply register x by 4 Doing both of those leal instructions is x*20 First multiply i (which is in %ebx) by 5 36 leal (%ebx,%ebx,4), %eax # i*5 # Now multiply that by 4 which effectively mult by 20 # and add the address of the beginning of the array 37 leal studentData+4(,%eax,4), %eax # (i*5) * 4