docs: def compile(self, ops):
          """
          Translate a list of operations into its assembler source.
  
          Arguments:
              ops(list): A list of shellcode operations.
  
          Returns:
              str: The assembler source code that implements the shellcode.
          """
  
          def _compile():
              code = []
  
              for op in ops:
                  if isinstance(op, SyscallInvoke):
                      code.extend(self.syscall(op))
                  elif isinstance(op, LoadRegister):
                      code.extend(self.reg_load(op.register, op.value))
                  elif isinstance(op, str):
                      code.extend(op.split('\n'))
                  else:
                      raise ValueError('No idea how to assemble "%s"' % repr(op))
              return ['\t%s' % line for line in code]
  
          # We do 2 passes to make sure all data is allocated so buffers point at the right offset.
          _compile()
          return '\n'.join(self.finalize(self.data_finalizer(_compile(), self.data))) + '\n'