|
发表于 2003-12-1 10:36:59
|
显示全部楼层
这是我学习时从网上找到的例子,后来我自己又写了一些,如果你需要的话,
我可以传给你。
; hello.asm (Intel格式)
section .data ; 数据段声明
msg db "Hello, world!", 0xA ; 要输出的字符串
len equ $ - msg ; 字串长度
section .text ; 代码段声明
global _start ; 指定入口函数
_start: ; 在屏幕上显示一个字符串
mov edx, len ; 参数三:字符串长度
mov ecx, msg ; 参数二:要显示的字符串
mov ebx, 1 ; 参数一:文件描述符(stdout)
mov eax, 4 ; 系统调用号(sys_write)
int 0x80 ; 调用内核功能
; 退出程序
mov ebx, 0 ; 参数一:退出代码
mov eax, 1 ; 系统调用号(sys_exit)
int 0x80 ; 调用内核功能
你应该能在linux装上nasm了吧,装上之后,执行:
nasm -f elf hello.asm
ld -o hello hello.o
我一般是用c写主main()函数,用汇编实现功能,下面是另一个比较大的例子:
/*ramio.c*/
#include <stdio.h>
void ram_io(); /* prototype for assembly routine */
int main(void)
{
ram_io();
return 0;
}
/*ramio.asm*/
;file: ramio.asm
%include "asm_io.inc"
%define CF_MASK 00000001h
%define PF_MASK 00000004h
%define AF_MASK 00000010h
%define ZF_MASK 00000040h
%define SF_MASK 00000080h
%define DF_MASK 00000400h
%define OF_MASK 00000800h
;%ifdef ELF_TYPE
%define _scanf scanf
%define _printf printf
;%define _getchar getchar
;%define _putchar putchar
;%define _fputs fputs
;%endif
%macro Set_GPIO18 1
mov al,%1
cmp al,1
je %%set_18_high
%%set_18_low:
mov dx,MKF_GPIO_BASE_ADDRESS + 0Ch + 2
in al,dx
and al,11111011b ; =251
out dx,al
jmp %%set_18_end
%%set_18_high:
mov dx,MKF_GPIO_BASE_ADDRESS + 0Ch + 2
in al,dx
or al,00000100b
out dx,al
%%set_18_end:
%endmacro
%macro Set_GPIO19 1
mov al,%1
cmp al,1
je %%set_19_high
%%set_19_low:
mov dx,MKF_GPIO_BASE_ADDRESS + 0Ch + 2
in al,dx
and al,11110111b
out dx,al
jmp %%set_19_end
%%set_19_high:
mov dx,MKF_GPIO_BASE_ADDRESS + 0Ch + 2
in al,dx
or al,00001000b
out dx,al
%%set_19_end:
%endmacro
%macro Win977AFReadIO 1
push dx
mov dx,IoIndexPort ; DX = index port address
mov al,%1
out dx, al ; Select I/O register
jcxz $+2
mov dx,IoDataPort ; DX = data port address
in al, dx ; AL = data
jcxz $+2
pop dx
%endmacro
%macro Win977AFWriteIO 2
push dx
mov dx, IoIndexPort ; DX = index port address
mov al,%1
out dx,al ; Select I/O register
jcxz $+2
mov dx, IoDataPort ; DX = data port address
mov al, %2 ; AH = Reg #, AL = Data to write
out dx, al
jcxz $+2
pop dx
%endmacro
%macro EnterConfig 0
cli
push ax
push dx
mov dx,IoIndexPort ; DX = index port address
mov al, 087h
out dx, al ; Write twice to enter config
jcxz $+2
out dx, al
pop dx
pop ax
%endmacro
%macro ExitConfig 0
push ax
push dx
mov dx, IoIndexPort ; DX = index port address
mov al, 0aah
out dx, al ; escape configuration mode
pop dx
pop ax
%endmacro
%macro SelectLogicalDevice 1
push ax
push dx
mov dx, IoIndexPort ;DX = index port address
mov al, 07h ;Logical device register
out dx, al
jcxz $+2
mov dx, IoDataPort ;DX = data port address
mov al, %1
out dx, al
pop dx
pop ax
%endmacro
_DATA_SEQ
MKF_GPIO_BASE_ADDRESS equ 4080h
IoIndexPort equ 3f0h
IoDataPort equ 3f1h
len equ 65536 ;NVRAM size per page
source db 00h
Menu db '1 => Write 64k bytes data to Page0',0dh,0ah
db '2 => Write 64k bytes data to Page1',0dh,0ah
db '3 => Read 64k bytes data from Page0',0dh,0ah
db '4 => Read 64k bytes data from Page1',0dh,0ah
db 'Other key => Exit the program',0dh,0ah
db 0dh,0ah
db 'Please select the item to execute: ',0
ScanfFormat db "%i", 0
StringFormat db "%s",0
CR_LF db 0ah,0dh,0
message0 db 'Page0 : Start writing data 64K bytes to D-segment....',0dh,0ah,0
message00 db 'Page1 : Start writing data 64k bytes to D-segment....',0dh,0ah,0
message1 db 0dh,0ah,'Page0 : End writing data to D-segment...',0dh,0ah,0
message11 db 0dh,0ah,'Page1 : End writing data to D-segment...',0dh,0ah,0
message2 db 'Page0:Start reading data from D-segment...',0dh,0ah,0
message22 db 'Page1 : Start reading data from D-segment....press any key',0dh,0ah,0
message3 db 0dh,0ah,'Page0 : End reading data from D-segment...',0dh,0ah,0
message33 db 0dh,0ah,'Page1 : End reading data from D-segment...',0dh,0ah,0
message5 db 'Please input test pattern: ',0
welcomemessage db 'welcom to use this program',0dh,0ah,0
_BSS_SEQ
;stack resb 200h
_TEXT_SEQ
global ram_io
extern _printf,_scanf
ram_io:
enter 0,0 ; setup routine
pusha
start_menu:
push dword Menu
call _printf
add esp,4
lea eax, [ebp-4] ; eax = address of local dword
push eax
push dword ScanfFormat
call _scanf
add esp, 8
mov eax,[ebp-4]
cmp dword eax,1 ; eax = return value of scanf
jne _not_1
call write_page0
jmp start_menu
_not_1:
cmp dword eax,2
jne _not_2
call write_page1
jmp start_menu
_not_2:
cmp dword eax,3
jne _not_3
call read_page0
jmp start_menu
_not_3:
cmp dword eax,4
jne _exit
call read_page1
jmp start_menu
_exit:
popa
mov eax, 0 ; return back to C
leave
ret
write_page0:
call print_null
push dword message0
call _printf
pop ecx
Set_GPIO19 0
mov byte [source],10101010b ;default test pattern
;user enter the test pattern
push dword message5
call _printf
pop ecx
lea eax, [ebp-4] ; eax = address of local dword
push eax
push dword ScanfFormat
call _scanf
add esp, 8
mov eax,[ebp-4]
cmp dword eax, 0dh
je _auto_test_pattern
mov byte [source],al ;save the keyin data to [source]
push eax ;print keyin data
push dword ScanfFormat
call _printf
pop ecx
pop ecx
_auto_test_pattern:
;write data to D segment
mov ax,0d000h
mov es,ax
lea si,[source]
mov ax,0
mov di,ax
mov ecx,len
_for1:
mov al,[ds]
mov [es],al
inc di
loop _for1,ecx
push dword message1
call _printf
pop ecx
ret
read_page0:
Set_GPIO19 0
call print_null
push dword message2
call _printf
pop ecx
lea eax, [ebp-4] ; eax = address of local dword
push eax
push dword ScanfFormat
call _scanf
add esp, 8
mov eax,[ebp-4]
mov ax,0d000h
mov es,ax
lea si,[source]
mov ax,0
mov di,ax
mov ecx,len
_for2:
mov dl,[es] ;Read data from NVRAM
push eax ;print keyin data
push dword ScanfFormat
call _printf
add esp, 8
inc di
loop _for2,ecx ;loop to _for2
push dword message3
call _printf
pop ecx
ret
write_page1:
call print_null
push dword message00
call _printf
pop ecx
Set_GPIO19 1
mov byte [source], 10101010b ;default test pattern
;user enter the test pattern
push dword message5
call _printf
pop ecx
lea eax, [ebp-4] ; eax = address of local dword
push eax
push dword ScanfFormat
call _scanf
add esp, 8
mov eax,[ebp-4]
cmp dword eax, 0dh
je _auto_test1_pattern
mov byte [source],al ;save the keyin data to [source]
push eax ;print keyin data
push dword ScanfFormat
call _printf
pop ecx
pop ecx
_auto_test1_pattern:
;write data to D segment
mov ax,0d000h
mov es,ax
lea si,[source]
mov ax,0
mov di,ax
mov ecx,len
_for3:
mov al,[ds]
mov [es],al
inc di
loop _for3,ecx
push dword message11
call _printf
pop ecx
ret
read_page1:
Set_GPIO19 1
call print_null
push dword message22
call _printf
pop ecx
lea eax, [ebp-4] ; eax = address of local dword
push eax
push dword ScanfFormat
call _scanf
add esp, 8
mov eax,[ebp-4]
;read data from D segment
mov ax,0d000h
mov es,ax
lea si,[source]
mov ax,0
mov di,ax
mov ecx,len
_for4:
mov dl,[es]
push eax ;print keyin data
push dword ScanfFormat
call _printf
add esp, 8
inc di
loop _for4,ecx ;loop to _for4
push dword message33
call _printf
pop ecx
ret
print_null:
push dword CR_LF
call _printf
pop ecx
ret
debug_int:
push eax
push dword ScanfFormat
call _printf
add esp,8
call print_null
ret
debug_string:
push eax
push dword StringFormat
call _printf
add esp,8
call print_null
ret
/*asm_io.inc*/
extern read_int, print_int, print_string
extern read_char, print_char, print_nl
extern sub_dump_regs, sub_dump_mem, sub_dump_math, sub_dump_stack
%macro dump_regs 1
push dword %1
call sub_dump_regs
%endmacro
;
; usage: dump_mem label, start-address, # paragraphs
%macro dump_mem 3
push dword %1
push dword %2
push dword %3
call sub_dump_mem
%endmacro
%macro dump_math 1
push dword %1
call sub_dump_math
%endmacro
%macro dump_stack 3
push dword %3
push dword %2
push dword %1
call sub_dump_stack
%endmacro
下面这个文件没有用,为了你以后可能使用,它相当于一些常用的函数,特加上:
/*asm_io.asm*/
;
; file: asm_io.asm
; Assembly I/O routines
; To assemble for DJGPP
; nasm -f coff -d COFF_TYPE asm_io.asm
; To assemble for Borland C++ 5.x
; nasm -f obj -d OBJ_TYPE asm_io.asm
; To assemble for Microsoft Visual Studio
; nasm -f win32 -d COFF_TYPE asm_io.asm
; To assemble for Linux
; nasm -f elf -d ELF_TYPE asm_io.asm
%define NL 10
%define CF_MASK 00000001h
%define PF_MASK 00000004h
%define AF_MASK 00000010h
%define ZF_MASK 00000040h
%define SF_MASK 00000080h
%define DF_MASK 00000400h
%define OF_MASK 00000800h
;
; Linux C doesn't put underscores on labels
;
%ifdef ELF_TYPE
%define _scanf scanf
%define _printf printf
%define _getchar getchar
%define _putchar putchar
%define _fputs fputs
%endif
%ifdef OBJ_TYPE
segment .data public align=4 class=data use32
%else
segment .data
%endif
int_format db "%i", 0
string_format db "%s", 0
reg_format db "Register Dump # %d", NL
db "EAX = %.8X EBX = %.8X ECX = %.8X EDX = %.8X", NL
db "ESI = %.8X EDI = %.8X EBP = %.8X ESP = %.8X", NL
db "EIP = %.8X FLAGS = %.4X %s %s %s %s %s %s %s", NL
db 0
carry_flag db "CF", 0
zero_flag db "ZF", 0
sign_flag db "SF", 0
parity_flag db "PF", 0
overflow_flag db "OF", 0
dir_flag db "DF", 0
aux_carry_flag db "AF", 0
unset_flag db " ", 0
mem_format1 db "Memory Dump # %d Address = %.8X", NL, 0
mem_format2 db "%.8X ", 0
mem_format3 db "%.2X ", 0
stack_format db "Stack Dump # %d", NL
db "EBP = %.8X ESP = %.8X", NL, 0
stack_line_format db "%+4d %.8X %.8X", NL, 0
math_format1 db "Math Coprocessor Dump # %d Control Word = %.4X"
db " Status Word = %.4X", NL, 0
valid_st_format db "ST%d: %.10g", NL, 0
invalid_st_format db "ST%d: Invalid ST", NL, 0
empty_st_format db "ST%d: Empty", NL, 0
;
; code is put in the _TEXT segment
;
%ifdef OBJ_TYPE
segment text public align=1 class=code use32
%else
segment .text
%endif
global read_int, print_int, print_string, read_char
global print_char, print_nl, sub_dump_regs, sub_dump_mem
global sub_dump_math, sub_dump_stack
extern _scanf, _printf, _getchar, _putchar, _fputs
read_int:
enter 4,0
pusha
pushf
lea eax, [ebp-4]
push eax
push dword int_format
call _scanf
pop ecx
pop ecx
popf
popa
mov eax, [ebp-4]
leave
ret
print_int:
enter 0,0
pusha
pushf
push eax
push dword int_format
call _printf
pop ecx
pop ecx
popf
popa
leave
ret
print_string:
enter 0,0
pusha
pushf
push eax
push dword string_format
call _printf
pop ecx
pop ecx
popf
popa
leave
ret
read_char:
enter 4,0
pusha
pushf
call _getchar
mov [ebp-4], eax
popf
popa
mov eax, [ebp-4]
leave
ret
print_char:
enter 0,0
pusha
pushf
push eax
call _putchar
pop ecx
popf
popa
leave
ret
print_nl:
enter 0,0
pusha
pushf
push dword 10 ; 10 == ASCII code for \n
call _putchar
pop ecx
popf
popa
leave
ret
sub_dump_regs:
enter 4,0
pusha
pushf
mov eax, [esp] ; read FLAGS back off stack
mov [ebp-4], eax ; save flags
;
; show which FLAGS are set
;
test eax, CF_MASK
jz cf_off
mov eax, carry_flag
jmp short push_cf
cf_off:
mov eax, unset_flag
push_cf:
push eax
test dword [ebp-4], PF_MASK
jz pf_off
mov eax, parity_flag
jmp short push_pf
pf_off:
mov eax, unset_flag
push_pf:
push eax
test dword [ebp-4], AF_MASK
jz af_off
mov eax, aux_carry_flag
jmp short push_af
af_off:
mov eax, unset_flag
push_af:
push eax
test dword [ebp-4], ZF_MASK
jz zf_off
mov eax, zero_flag
jmp short push_zf
zf_off:
mov eax, unset_flag
push_zf:
push eax
test dword [ebp-4], SF_MASK
jz sf_off
mov eax, sign_flag
jmp short push_sf
sf_off:
mov eax, unset_flag
push_sf:
push eax
test dword [ebp-4], DF_MASK
jz df_off
mov eax, dir_flag
jmp short push_df
df_off:
mov eax, unset_flag
push_df:
push eax
test dword [ebp-4], OF_MASK
jz of_off
mov eax, overflow_flag
jmp short push_of
of_off:
mov eax, unset_flag
push_of:
push eax
push dword [ebp-4] ; FLAGS
mov eax, [ebp+4]
sub eax, 10 ; EIP on stack is 10 bytes ahead of orig
push eax ; EIP
lea eax, [ebp+12]
push eax ; original ESP
push dword [ebp] ; original EBP
push edi
push esi
push edx
push ecx
push ebx
push dword [ebp-8] ; original EAX
push dword [ebp+8] ; # of dump
push dword reg_format
call _printf
add esp, 76
popf
popa
leave
ret 4
sub_dump_stack:
enter 0,0
pusha
pushf
lea eax, [ebp+20]
push eax ; original ESP
push dword [ebp] ; original EBP
push dword [ebp+8] ; # of dump
push dword stack_format
call _printf
add esp, 16
mov ebx, [ebp] ; ebx = original ebp
mov eax, [ebp+16] ; eax = # dwords above ebp
shl eax, 2 ; eax *= 4
add ebx, eax ; ebx = & highest dword in stack to display
mov edx, [ebp+16]
mov ecx, edx
add ecx, [ebp+12]
inc ecx ; ecx = # of dwords to display
stack_line_loop:
push edx
push ecx ; save ecx & edx
push dword [ebx] ; value on stack
push ebx ; address of value on stack
mov eax, edx
sal eax, 2 ; eax = 4*edx
push eax ; offset from ebp
push dword stack_line_format
call _printf
add esp, 16
pop ecx
pop edx
sub ebx, 4
dec edx
loop stack_line_loop
popf
popa
leave
ret 12
sub_dump_mem:
enter 0,0
pusha
pushf
push dword [ebp+12]
push dword [ebp+16]
push dword mem_format1
call _printf
add esp, 12
mov esi, [ebp+12] ; address
and esi, 0FFFFFFF0h ; move to start of paragraph
mov ecx, [ebp+8]
inc ecx
mem_outer_loop:
push ecx
push esi
push dword mem_format2
call _printf
add esp, 8
xor ebx, ebx
mem_hex_loop:
xor eax, eax
mov al, [esi + ebx]
push eax
push dword mem_format3
call _printf
add esp, 8
inc ebx
cmp ebx, 16
jl mem_hex_loop
mov eax, '"'
call print_char
xor ebx, ebx
mem_char_loop:
xor eax, eax
mov al, [esi+ebx]
cmp al, 32
jl non_printable
cmp al, 126
jg non_printable
jmp short mem_char_loop_continue
non_printable:
mov eax, '?'
mem_char_loop_continue:
call print_char
inc ebx
cmp ebx, 16
jl mem_char_loop
mov eax, '"'
call print_char
call print_nl
add esi, 16
pop ecx
loop mem_outer_loop
popf
popa
leave
ret 12
; function sub_dump_math
; prints out state of math coprocessor without modifying the coprocessor
; or regular processor state
; Parameters:
; dump number - dword at [ebp+8]
; Local variables:
; ebp-108 start of fsave buffer
; ebp-116 temp double
; Notes: This procedure uses the Pascal convention.
; fsave buffer structure:
; ebp-108 control word
; ebp-104 status word
; ebp-100 tag word
; ebp-80 ST0
; ebp-70 ST1
; ebp-60 ST2 ...
; ebp-10 ST7
;
sub_dump_math:
enter 116,0
pusha
pushf
fsave [ebp-108] ; save coprocessor state to memory
mov eax, [ebp-104] ; status word
and eax, 0FFFFh
push eax
mov eax, [ebp-108] ; control word
and eax, 0FFFFh
push eax
push dword [ebp+8]
push dword math_format1
call _printf
add esp, 16
;
; rotate tag word so that tags in same order as numbers are
; in the stack
;
mov cx, [ebp-104] ; ax = status word
shr cx, 11
and cx, 7 ; cl = physical state of number on stack top
mov bx, [ebp-100] ; bx = tag word
shl cl,1 ; cl *= 2
ror bx, cl ; move top of stack tag to lowest bits
mov edi, 0 ; edi = stack number of number
lea esi, [ebp-80] ; esi = address of ST0
mov ecx, 8 ; ecx = loop counter
tag_loop:
push ecx
mov ax, 3
and ax, bx ; ax = current tag
or ax, ax ; 00 -> valid number
je valid_st
cmp ax, 1 ; 01 -> zero
je zero_st
cmp ax, 2 ; 10 -> invalid number
je invalid_st
push edi ; 11 -> empty
push dword empty_st_format
call _printf
add esp, 8
jmp short cont_tag_loop
zero_st:
fldz
jmp short print_real
valid_st:
fld tword [esi]
print_real:
fstp qword [ebp-116]
push dword [ebp-112]
push dword [ebp-116]
push edi
push dword valid_st_format
call _printf
add esp, 16
jmp short cont_tag_loop
invalid_st:
push edi
push dword invalid_st_format
call _printf
add esp, 8
cont_tag_loop:
ror bx, 2 ; mov next tag into lowest bits
inc edi
add esi, 10 ; mov to next number on stack
pop ecx
loop tag_loop
frstor [ebp-108] ; restore coprocessor state
popf
popa
leave
ret 4
在linux下,执行:
nasm -f elf ramio.asm
gcc -o ramio ramio.c ramio.o
(全文完) |
|