mirror of
https://github.com/ioacademy-jikim/debugging
synced 2025-06-08 16:36:21 +00:00
494 lines
12 KiB
ArmAsm
494 lines
12 KiB
ArmAsm
#
|
|
# linux_logo in ARM assembly language
|
|
# based on the code from ll_asm-0.41
|
|
#
|
|
# By Vince Weaver <vince _at_ deater.net>
|
|
#
|
|
# Modified to remove non-deterministic system calls
|
|
# And to avoid reading from /proc
|
|
|
|
.include "logo.include"
|
|
|
|
# offsets into the results returned by the uname syscall
|
|
.equ U_SYSNAME,0
|
|
.equ U_NODENAME,65
|
|
.equ U_RELEASE,65*2
|
|
.equ U_VERSION,(65*3)
|
|
.equ U_MACHINE,(65*4)
|
|
.equ U_DOMAINNAME,65*5
|
|
|
|
# offset into the results returned by the sysinfo syscall
|
|
.equ S_TOTALRAM,16
|
|
|
|
# Sycscalls
|
|
.equ SYSCALL_EXIT, 1
|
|
.equ SYSCALL_WRITE, 4
|
|
|
|
#
|
|
.equ STDIN,0
|
|
.equ STDOUT,1
|
|
.equ STDERR,2
|
|
|
|
.globl _start
|
|
_start:
|
|
ldr r11,data_addr
|
|
ldr r12,bss_addr
|
|
|
|
#=========================
|
|
# PRINT LOGO
|
|
#=========================
|
|
|
|
# LZSS decompression algorithm implementation
|
|
# by Stephan Walter 2002, based on LZSS.C by Haruhiko Okumura 1989
|
|
# optimized some more by Vince Weaver
|
|
|
|
ldr r1,out_addr @ buffer we are printing to
|
|
|
|
mov r2,#(N-F) @ R
|
|
|
|
add r3,r11,#(logo-data_begin)
|
|
@ r3 points to logo data
|
|
ldr r8,logo_end_addr
|
|
@ r8 points to logo end
|
|
ldr r9,text_addr @ r9 points to text buf
|
|
|
|
decompression_loop:
|
|
ldrb r4,[r3],#+1 @ load a byte, increment pointer
|
|
|
|
mov r5,#0xff @ load top as a hackish 8-bit counter
|
|
orr r5,r4,r5,LSL #8 @ shift 0xff left by 8 and or in the byte we loaded
|
|
|
|
test_flags:
|
|
cmp r3,r8 @ have we reached the end?
|
|
bge done_logo @ if so, exit
|
|
|
|
lsrs r5,#1 @ shift bottom bit into carry flag
|
|
bcs discrete_char @ if set, we jump to discrete char
|
|
|
|
offset_length:
|
|
ldrb r0,[r3],#+1 @ load a byte, increment pointer
|
|
ldrb r4,[r3],#+1 @ load a byte, increment pointer
|
|
@ we can't load halfword as no unaligned loads on arm
|
|
|
|
orr r4,r0,r4,LSL #8 @ merge back into 16 bits
|
|
@ this has match_length and match_position
|
|
|
|
mov r7,r4 @ copy r4 to r7
|
|
@ no need to mask r7, as we do it
|
|
@ by default in output_loop
|
|
|
|
mov r0,#(THRESHOLD+1)
|
|
add r6,r0,r4,LSR #(P_BITS)
|
|
@ r6 = (r4 >> P_BITS) + THRESHOLD + 1
|
|
@ (=match_length)
|
|
|
|
output_loop:
|
|
ldr r0,pos_mask @ urgh, can't handle simple constants
|
|
and r7,r7,r0 @ mask it
|
|
ldrb r4,[r9,r7] @ load byte from text_buf[]
|
|
add r7,r7,#1 @ advance pointer in text_buf
|
|
|
|
store_byte:
|
|
strb r4,[r1],#+1 @ store a byte, increment pointer
|
|
strb r4,[r9,r2] @ store a byte to text_buf[r]
|
|
add r2,r2,#1 @ r++
|
|
mov r0,#(N)
|
|
sub r0,r0,#1 @ grrr no way to get this easier
|
|
and r2,r2,r0 @ mask r
|
|
|
|
subs r6,r6,#1 @ decement count
|
|
bne output_loop @ repeat until k>j
|
|
|
|
tst r5,#0xff00 @ are the top bits 0?
|
|
bne test_flags @ if not, re-load flags
|
|
|
|
b decompression_loop
|
|
|
|
discrete_char:
|
|
ldrb r4,[r3],#+1 @ load a byte, increment pointer
|
|
mov r6,#1 @ we set r6 to one so byte
|
|
@ will be output once
|
|
|
|
b store_byte @ and store it
|
|
|
|
|
|
# end of LZSS code
|
|
|
|
done_logo:
|
|
ldr r1,out_addr @ buffer we are printing to
|
|
|
|
bl write_stdout @ print the logo
|
|
|
|
#==========================
|
|
# PRINT VERSION
|
|
#==========================
|
|
first_line:
|
|
|
|
mov r0,#0
|
|
add r1,r11,#(uname_info-data_begin)
|
|
@ os-name from uname "Linux"
|
|
|
|
ldr r10,out_addr @ point r10 to out_buffer
|
|
|
|
bl strcat @ call strcat
|
|
|
|
|
|
add r1,r11,#(ver_string-data_begin) @ source is " Version "
|
|
bl strcat @ call strcat
|
|
|
|
add r1,r11,#((uname_info-data_begin)+U_RELEASE)
|
|
@ version from uname, ie "2.6.20"
|
|
bl strcat @ call strcat
|
|
|
|
add r1,r11,#(compiled_string-data_begin)
|
|
@ source is ", Compiled "
|
|
bl strcat @ call strcat
|
|
|
|
add r1,r11,#((uname_info-data_begin)+U_VERSION)
|
|
@ compiled date
|
|
bl strcat @ call strcat
|
|
|
|
mov r3,#0xa
|
|
strb r3,[r10],#+1 @ store a linefeed, increment pointer
|
|
strb r0,[r10],#+1 @ NUL terminate, increment pointer
|
|
|
|
bl center_and_print @ center and print
|
|
|
|
@===============================
|
|
@ Middle-Line
|
|
@===============================
|
|
middle_line:
|
|
@=========
|
|
@ Load /proc/cpuinfo into buffer
|
|
@=========
|
|
|
|
ldr r10,out_addr @ point r10 to out_buffer
|
|
|
|
@=============
|
|
@ Number of CPUs
|
|
@=============
|
|
number_of_cpus:
|
|
|
|
add r1,r11,#(one-data_begin)
|
|
# cheat. Who has an SMP arm?
|
|
bl strcat
|
|
|
|
@=========
|
|
@ MHz
|
|
@=========
|
|
print_mhz:
|
|
|
|
@ the arm system I have does not report MHz
|
|
|
|
@=========
|
|
@ Chip Name
|
|
@=========
|
|
chip_name:
|
|
mov r0,#'s'
|
|
mov r1,#'o'
|
|
mov r2,#'r'
|
|
mov r3,#' '
|
|
bl find_string
|
|
@ find 'sor\t: ' and grab up to ' '
|
|
|
|
add r1,r11,#(processor-data_begin)
|
|
@ print " Processor, "
|
|
bl strcat
|
|
|
|
@========
|
|
@ RAM
|
|
@========
|
|
|
|
|
|
ldr r3,[r11,#((sysinfo_buff-data_begin)+S_TOTALRAM)]
|
|
@ size in bytes of RAM
|
|
movs r3,r3,lsr #20 @ divide by 1024*1024 to get M
|
|
adc r3,r3,#0 @ round
|
|
|
|
mov r0,#1
|
|
bl num_to_ascii
|
|
|
|
add r1,r11,#(ram_comma-data_begin)
|
|
@ print 'M RAM, '
|
|
bl strcat @ call strcat
|
|
|
|
|
|
@========
|
|
@ Bogomips
|
|
@========
|
|
|
|
mov r0,#'I'
|
|
mov r1,#'P'
|
|
mov r2,#'S'
|
|
mov r3,#'\n'
|
|
bl find_string
|
|
|
|
add r1,r11,#(bogo_total-data_begin)
|
|
bl strcat @ print bogomips total
|
|
|
|
bl center_and_print @ center and print
|
|
|
|
#=================================
|
|
# Print Host Name
|
|
#=================================
|
|
last_line:
|
|
ldr r10,out_addr @ point r10 to out_buffer
|
|
|
|
add r1,r11,#((uname_info-data_begin)+U_NODENAME)
|
|
@ host name from uname()
|
|
bl strcat @ call strcat
|
|
|
|
bl center_and_print @ center and print
|
|
|
|
add r1,r11,#(default_colors-data_begin)
|
|
@ restore colors, print a few linefeeds
|
|
bl write_stdout
|
|
|
|
|
|
@================================
|
|
@ Exit
|
|
@================================
|
|
exit:
|
|
mov r0,#0 @ result is zero
|
|
mov r7,#SYSCALL_EXIT
|
|
swi 0x0 @ and exit
|
|
|
|
|
|
@=================================
|
|
@ FIND_STRING
|
|
@=================================
|
|
@ r0,r1,r2 = string to find
|
|
@ r3 = char to end at
|
|
@ r5 trashed
|
|
find_string:
|
|
ldr r7,disk_addr @ look in cpuinfo buffer
|
|
find_loop:
|
|
ldrb r5,[r7],#+1 @ load a byte, increment pointer
|
|
cmp r5,r0 @ compare against first byte
|
|
ldrb r5,[r7] @ load next byte
|
|
cmpeq r5,r1 @ if first byte matched, comp this one
|
|
ldrb r5,[r7,#+1] @ load next byte
|
|
cmpeq r5,r2 @ if first two matched, comp this one
|
|
beq find_colon @ if all 3 matched, we are found
|
|
|
|
cmp r5,#0 @ are we at EOF?
|
|
beq done @ if so, done
|
|
|
|
b find_loop
|
|
|
|
find_colon:
|
|
ldrb r5,[r7],#+1 @ load a byte, increment pointer
|
|
cmp r5,#':'
|
|
bne find_colon @ repeat till we find colon
|
|
|
|
add r7,r7,#1 @ skip the space
|
|
|
|
store_loop:
|
|
ldrb r5,[r7],#+1 @ load a byte, increment pointer
|
|
strb r5,[r10],#+1 @ store a byte, increment pointer
|
|
cmp r5,r3
|
|
bne store_loop
|
|
|
|
almost_done:
|
|
mov r0,#0
|
|
strb r0,[r10],#-1 @ replace last value with NUL
|
|
|
|
done:
|
|
bx r14 @ return
|
|
|
|
#================================
|
|
# strcat
|
|
#================================
|
|
# value to cat in r1
|
|
# output buffer in r10
|
|
# r3 trashed
|
|
strcat:
|
|
ldrb r3,[r1],#+1 @ load a byte, increment pointer
|
|
strb r3,[r10],#+1 @ store a byte, increment pointer
|
|
cmp r3,#0 @ is it zero?
|
|
bne strcat @ if not loop
|
|
sub r10,r10,#1 @ point to one less than null
|
|
bx r14 @ return
|
|
|
|
|
|
#==============================
|
|
# center_and_print
|
|
#==============================
|
|
# string to center in at output_buffer
|
|
|
|
center_and_print:
|
|
|
|
stmfd SP!,{LR} @ store return address on stack
|
|
|
|
add r1,r11,#(escape-data_begin)
|
|
@ we want to output ^[[
|
|
bl write_stdout
|
|
|
|
str_loop2:
|
|
ldr r2,out_addr @ point r2 to out_buffer
|
|
sub r2,r10,r2 @ get length by subtracting
|
|
|
|
rsb r2,r2,#81 @ reverse subtract! r2=81-r2
|
|
@ we use 81 to not count ending \n
|
|
|
|
bne done_center @ if result negative, don't center
|
|
|
|
lsrs r3,r2,#1 @ divide by 2
|
|
adc r3,r3,#0 @ round?
|
|
|
|
mov r0,#0 @ print to stdout
|
|
bl num_to_ascii @ print number of spaces
|
|
|
|
add r1,r11,#(C-data_begin)
|
|
@ we want to output C
|
|
bl write_stdout
|
|
|
|
done_center:
|
|
ldr r1,out_addr @ point r1 to out_buffer
|
|
ldmfd SP!,{LR} @ restore return address from stack
|
|
|
|
#================================
|
|
# WRITE_STDOUT
|
|
#================================
|
|
# r1 has string
|
|
# r0,r2,r3 trashed
|
|
write_stdout:
|
|
mov r2,#0 @ clear count
|
|
|
|
str_loop1:
|
|
add r2,r2,#1
|
|
ldrb r3,[r1,r2]
|
|
cmp r3,#0
|
|
bne str_loop1 @ repeat till zero
|
|
|
|
write_stdout_we_know_size:
|
|
mov r0,#STDOUT @ print to stdout
|
|
mov r7,#SYSCALL_WRITE
|
|
swi 0x0 @ run the syscall
|
|
bx r14 @ return
|
|
|
|
|
|
@#############################
|
|
@ num_to_ascii
|
|
@#############################
|
|
@ r3 = value to print
|
|
@ r0 = 0=stdout, 1=strcat
|
|
|
|
num_to_ascii:
|
|
stmfd SP!,{r10,LR} @ store return address on stack
|
|
add r10,r12,#((ascii_buffer-bss_begin))
|
|
add r10,r10,#10
|
|
@ point to end of our buffer
|
|
|
|
mov r4,#10 @ we'll be dividing by 10
|
|
div_by_10:
|
|
bl divide @ Q=r7,$0, R=r8,$1
|
|
add r8,r8,#0x30 @ convert to ascii
|
|
strb r8,[r10],#-1 @ store a byte, decrement pointer
|
|
adds r3,r7,#0 @ move Q in for next divide, update flags
|
|
bne div_by_10 @ if Q not zero, loop
|
|
|
|
write_out:
|
|
add r1,r10,#1 @ adjust pointer
|
|
ldmfd SP!,{r10,LR} @ restore return address from stack
|
|
|
|
cmp r0,#0
|
|
bne strcat @ if 1, strcat
|
|
|
|
b write_stdout @ else, fallthrough to stdout
|
|
|
|
|
|
@===================================================
|
|
@ Divide - because ARM has no hardware int divide
|
|
@ yes this is an awful algorithm, but simple
|
|
@ and uses few registers
|
|
@==================================================
|
|
@ r3=numerator r4=denominator
|
|
@ r7=quotient r8=remainder
|
|
@ r5=trashed
|
|
divide:
|
|
|
|
mov r7,#0 @ zero out quotient
|
|
divide_loop:
|
|
mul r5,r7,r4 @ multiply Q by denominator
|
|
add r7,r7,#1 @ increment quotient
|
|
cmp r5,r3 @ is it greater than numerator?
|
|
ble divide_loop @ if not, loop
|
|
sub r7,r7,#2 @ otherwise went too far, decrement
|
|
@ and done
|
|
|
|
mul r5,r7,r4 @ calculate remainder
|
|
sub r8,r3,r5 @ R=N-(Q*D)
|
|
bx r14 @ return
|
|
|
|
|
|
bss_addr: .word bss_begin
|
|
data_addr: .word data_begin
|
|
out_addr: .word out_buffer
|
|
disk_addr: .word disk_buffer
|
|
logo_end_addr: .word logo_end
|
|
pos_mask: .word ((POSITION_MASK<<8)+0xff)
|
|
text_addr: .word text_buf
|
|
|
|
#===========================================================================
|
|
# section .data
|
|
#===========================================================================
|
|
.data
|
|
data_begin:
|
|
ver_string: .ascii " Version \0"
|
|
compiled_string: .ascii ", Compiled \0"
|
|
processor: .ascii " Processor, \0"
|
|
ram_comma: .ascii "M RAM, \0"
|
|
bogo_total: .ascii " Bogomips Total\n\0"
|
|
|
|
default_colors: .ascii "\033[0m\n\n\0"
|
|
escape: .ascii "\033[\0"
|
|
C: .ascii "C\0"
|
|
|
|
one: .ascii "One \0"
|
|
|
|
uname_info:
|
|
.ascii "Linux\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
|
.ascii "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
|
.ascii "lindt\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
|
.ascii "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
|
.ascii "2.6.32\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
|
.ascii "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
|
.ascii "#1 Wed May 13 15:51:54 UTC 2009\0"
|
|
.ascii "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
|
.ascii "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
|
.ascii "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
|
.ascii "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
|
.ascii "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
|
|
|
|
|
disk_buffer:
|
|
.ascii "Processor : Feroceon 88FR131 rev 1 (v5l)\n"
|
|
.ascii "BogoMIPS : 1192.75\n"
|
|
.ascii "Features : swp half thumb fastmult edsp \n"
|
|
.ascii "CPU implementer : 0x56\n"
|
|
.ascii "CPU architecture: 5TE\n"
|
|
.ascii "CPU variant : 0x2\n"
|
|
.ascii "CPU part : 0x131\n"
|
|
.ascii "CPU revision : 1\n"
|
|
.ascii "\n"
|
|
.ascii "Hardware : Marvell SheevaPlug Reference Board\n"
|
|
.ascii "Revision : 0000\n"
|
|
.ascii "Serial : 0000000000000000\n\0"
|
|
|
|
|
|
sysinfo_buff:
|
|
.long 0,0,0,0,512*1024*1024,0,0,0
|
|
|
|
.include "logo.lzss_new"
|
|
|
|
|
|
#============================================================================
|
|
# section .bss
|
|
#============================================================================
|
|
.bss
|
|
bss_begin:
|
|
.lcomm ascii_buffer,10
|
|
.lcomm text_buf, (N+F-1)
|
|
.lcomm out_buffer,16384
|