//---------------------------------------------------------------- // stkdump.s // // This program sends a hexadecimal and ascii dump of the // initial user stack area to the standard output device. // It was written in order to investigate the arrangement // of command-line arguments and environment variables in // stand-alone assembly language programs (i.e., programs // that do not get linked to standard runtime libraries). // // assemble using: $ as stkdump.s -o stkdump.o // and link using: $ ld stkdump.o -o stkdump // // programmer: ALLAN CRUSE // written on: 31 OCT 2003 //---------------------------------------------------------------- .equ TOP, 0xC0000000 # top of user's memory .section .data digits: .ascii "0123456789ABCDEF" # array of hex numerals buf: .zero 80 # output-buffer storage .section .text eax2hex: # # This is a 'helper' function: it converts the value found in EAX # into a hexadecimal digit-string at the address found in EDI. # # EXPECTS: EAX = longword to be converted into hexadecimal # EDI = buffer-address for the hexadecimal string # pushl %eax # save work registers pushl %ebx pushl %ecx pushl %edx cld # forward processing movl $digits, %ebx # translation table movl %eax, %edx # copy value to EDX movl $8, %ecx # number of nybbles nxnyb: roll $4, %edx # next nybble to DL movb %dl, %al # copy nybble to AL andb $0xF, %al # isolate the nybble xlat # convert to numeral stosb # write it to buffer loop nxnyb # process the others popl %edx # restore registers popl %ecx popl %ebx popl %eax ret .globl _start _start: movl %esp, %ebp # stacktop address cld # forward processing nxpara: # output the address for the current paragraph movl %ebp, %eax # value to display movl $buf, %edi # output buffer call eax2hex # write the value movb $':', %al # append a colon movb $' ', %ah # and then a blank stosw # as seperators # dump the current paragraph in hexadecimal format movl %ebp, %esi # point ESI to paragraph movl $4, %ecx # longwords-per-paragraph nxelt: lodsl # load next longword call eax2hex # output as hexadecimal movb $' ', %al # then a blank space stosb # output as a seperator loop nxelt # do the next longword # dump the current paragraph in printable ascii characters movl %ebp, %esi # point ESI to paragraph movl $16, %ecx # bytes per paragraph nxasc: lodsb # get the next byte cmpb $0x20, %al # does it preceed 0x20? jb dotit # yes, substitute a dot cmpb $0x7E, %al # does it follow 0x7E? ja dotit # yes, substitute a dot jmp nochg # else retain it intact dotit: movb $'.', %al # overwrite AL with dot nochg: stosb # store AL into buffer loop nxasc # and do the next byte movb $'\n', %al # append a newline code stosb # to the buffer output # now write the buffer contents to standard output movl $4, %eax # service-number movl $1, %ebx # device handle movl $buf, %ecx # buffer address movl %edi, %edx # buffer length subl $buf, %edx # is computed int $0x80 # enter the kernel # advance EBP to address the next stack paragraph addl $16, %ebp # 16 bytes-per-paragraph cmpl $TOP, %ebp # check: end-of-stack? jb nxpara # no, still more to do # terminate program movl $1, %eax # service-number movl $0, %ebx # exit-code value int $0x80 # enter the kernel .globl _start