专栏博客链接
《操作系统真象还原》从零开始自制操作系统 全章节博客链接
lib/kernel相关文件
编写完的bitmap.c
#include "bitmap.h"
#include "global.h"
#include "string.h"
#include "interrupt.h"
#include "print.h"
#include "debug.h"
#define BITMAP_MASK 1
void bitmap_init(struct bitmap* btmp)
{
memset(btmp->bits,0,btmp->btmp_bytes_len);
return;
}
bool bitmap_scan_test(struct bitmap* btmp,uint32_t bit_idx)
{
uint32_t byte_idx = bit_idx/8;
uint32_t byte_pos = bit_idx%8;
return (btmp->bits[byte_idx] & (BITMAP_MASK << byte_pos));
}
int bitmap_scan(struct bitmap* btmp, uint32_t cnt) {
uint32_t idx_byte = 0;
while (( 0xff == btmp->bits[idx_byte]) && (idx_byte < btmp->btmp_bytes_len)) {
idx_byte++;
}
ASSERT(idx_byte < btmp->btmp_bytes_len);
if (idx_byte == btmp->btmp_bytes_len) {
return -1;
}
int idx_bit = 0;
while ((uint8_t)(BITMAP_MASK << idx_bit) & btmp->bits[idx_byte]) {
idx_bit++;
}
int bit_idx_start = idx_byte * 8 + idx_bit;
if (cnt == 1) {
return bit_idx_start;
}
uint32_t bit_left = (btmp->btmp_bytes_len * 8 - bit_idx_start);
uint32_t next_bit = bit_idx_start + 1;
uint32_t count = 1;
bit_idx_start = -1;
while (bit_left-- > 0) {
if (!(bitmap_scan_test(btmp, next_bit))) {
count++;
} else {
count = 0;
}
if (count == cnt) {
bit_idx_start = next_bit - cnt + 1;
break;
}
next_bit++;
}
return bit_idx_start;
}
void bitmap_set(struct bitmap* btmp,uint32_t bit_idx,int8_t value)
{
ASSERT(value == 1 || value == 0);
uint32_t byte_idx = bit_idx/8;
uint32_t byte_pos = bit_idx%8;
if(value) btmp->bits[byte_idx] |= (BITMAP_MASK << byte_pos);
else btmp->bits[byte_idx] &= ~(BITMAP_MASK << byte_pos);
return;
}
编写完的bitmap.h
#ifndef __LIB_KERNEL_BITMAP_H
#define __LIB_KERNEL_BITMAP_H
#include "global.h"
#include "stdint.h"
#define BITMAP_MASK 1
struct bitmap
{
uint32_t btmp_bytes_len;
uint8_t* bits;
};
void bitmap_init(struct bitmap* btmp);
bool bitmap_scan_test(struct bitmap* btmp,uint32_t bit_idx);
int bitmap_scan(struct bitmap* btmp,uint32_t cnt);
void bitmap_set(struct bitmap* btmp,uint32_t bit_idx,int8_t value);
#endif
编写完的io.h
#ifndef __LIB_IO_H
#define __LIB_IO_H
#include "stdint.h"
static inline void outb(uint16_t port, uint8_t data) {
asm volatile ( "outb %b0, %w1" : : "a" (data), "Nd" (port));
}
static inline void outsw(uint16_t port, const void* addr, uint32_t word_cnt) {
asm volatile ("cld; rep outsw" : "+S" (addr), "+c" (word_cnt) : "d" (port));
}
static inline uint8_t inb(uint16_t port) {
uint8_t data;
asm volatile ("inb %w1, %b0" : "=a" (data) : "Nd" (port));
return data;
}
static inline void insw(uint16_t port, void* addr, uint32_t word_cnt) {
asm volatile ("cld; rep insw" : "+D" (addr), "+c" (word_cnt) : "d" (port) : "memory");
}
#endif
编写完的list.c
#include "list.h"
#include "interrupt.h"
#include "stdint.h"
#include "debug.h"
#define NULL 0
void list_init(struct list* list)
{
list->head.prev = NULL;
list->head.next = &list->tail;
list->tail.prev = &list->head;
list->tail.next = NULL;
}
void list_insert_before(struct list_elem* before,struct list_elem* elem)
{
enum intr_status old_status = intr_disable();
before->prev->next = elem;
elem->prev = before->prev;
elem->next = before;
before->prev = elem;
intr_set_status(old_status);
}
void list_push(struct list* plist,struct list_elem* elem)
{
list_insert_before(plist->head.next,elem);
}
void list_append(struct list* plist,struct list_elem* elem)
{
list_insert_before(&plist->tail,elem);
}
void list_remove(struct list_elem* pelem)
{
enum intr_status old_status = intr_disable();
pelem->prev->next = pelem->next;
pelem->next->prev = pelem->prev;
intr_set_status(old_status);
}
struct list_elem* list_pop(struct list* plist)
{
struct list_elem* ret = plist->head.next;
list_remove(ret);
return ret;
}
bool list_empty(struct list* plist)
{
return (plist->head.next == &plist->tail ? true : false);
}
uint32_t list_len(struct list* plist)
{
uint32_t ret = 0;
struct list_elem* next = plist->head.next;
while(next != &plist->tail)
{
next = next->next;
++ret;
}
return ret;
}
struct list_elem* list_traversal(struct list* plist,function func,int arg)
{
struct list_elem* elem = plist->head.next;
if(list_empty(plist)) return NULL;
while(elem != &plist->tail)
{
if(func(elem,arg)) return elem;
elem = elem->next;
}
return NULL;
}
bool elem_find(struct list* plist,struct list_elem* obj_elem)
{
struct list_elem* ptr = plist->head.next;
while(ptr != &plist->tail)
{
if(ptr == obj_elem) return true;
ptr = ptr->next;
}
return false;
}
编写完的list.h
#ifndef __LIB_KERNEL_LIST_H
#define __LIB_KERNEL_LIST_H
#include "stdint.h"
struct list_elem
{
struct list_elem* prev;
struct list_elem* next;
};
struct list
{
struct list_elem head;
struct list_elem tail;
};
typedef bool (function) (struct list_elem*,int arg);
void list_init(struct list*);
void list_insert_before(struct list_elem* before,struct list_elem* elem);
void list_push(struct list* plist,struct list_elem* elem);
void list_append(struct list* plist,struct list_elem* elem);
void list_remove(struct list_elem* pelem);
struct list_elem* list_pop(struct list* plist);
bool list_empty(struct list* plist);
uint32_t list_len(struct list* plist);
struct list_elem* list_traversal(struct list* plist,function func,int arg);
bool elem_find(struct list* plist,struct list_elem* obj_elem);
#endif
编写完的print.h
#ifndef __LIB_KERNEL_PRINT_H
#define __LIB_KERNEL_PRINT_H
#include "stdint.h"
void put_char(uint8_t char_asci);
void put_str(char* message);
void put_int(uint32_t num);
void cls_screen(void);
#endif
编写完的print.S
TI_GDT equ 0
RPL0 equ 0
SELECTOR_VIDEO equ (0x0003<<3) + TI_GDT + RPL0
section .data
put_int_buffer dq 0 ; 定义8字节缓冲区用于数字到字符的转换
[bits 32]
section .text
;--------------------------------------------
;put_str 通过put_char来打印以0字符结尾的字符串
;--------------------------------------------
global put_str
put_str:
;由于本函数中只用到了ebx和ecx,只备份这两个寄存器
push ebx
push ecx
xor ecx, ecx ; 准备用ecx存储参数,清空
mov ebx, [esp + 12] ; 从栈中得到待打印的字符串地址
.goon:
mov cl, [ebx]
cmp cl, 0 ; 如果处理到了字符串尾,跳到结束处返回
jz .str_over
push ecx ; 为put_char函数传递参数
call put_char
add esp, 4 ; 回收参数所占的栈空间
inc ebx ; 使ebx指向下一个字符
jmp .goon
.str_over:
pop ecx
pop ebx
ret
;-------------------- 将小端字节序的数字变成对应的ascii后,倒置 -----------------------
;输入:栈中参数为待打印的数字
;输出:在屏幕上打印16进制数字,并不会打印前缀0x,如打印10进制15时,只会直接打印f,不会是0xf
;------------------------------------------------------------------------------------------
global put_int
put_int:
pushad
mov ebp, esp
mov eax, [ebp+4*9] ; call的返回地址占4字节+pushad的8个4字节
mov edx, eax
mov edi, 7 ; 指定在put_int_buffer中初始的偏移量
mov ecx, 8 ; 32位数字中,16进制数字的位数是8个
mov ebx, put_int_buffer
;将32位数字按照16进制的形式从低位到高位逐个处理,共处理8个16进制数字
.16based_4bits: ; 每4位二进制是16进制数字的1位,遍历每一位16进制数字
and edx, 0x0000000F ; 解析16进制数字的每一位。and与操作后,edx只有低4位有效
cmp edx, 9 ; 数字0~9和a~f需要分别处理成对应的字符
jg .is_A2F
add edx, '0' ; ascii码是8位大小。add求和操作后,edx低8位有效。
jmp .store
.is_A2F:
sub edx, 10 ; A~F 减去10 所得到的差,再加上字符A的ascii码,便是A~F对应的ascii码
add edx, 'A'
;将每一位数字转换成对应的字符后,按照类似“大端”的顺序存储到缓冲区put_int_buffer
;高位字符放在低地址,低位字符要放在高地址,这样和大端字节序类似,只不过咱们这里是字符序.
.store:
; 此时dl中应该是数字对应的字符的ascii码
mov [ebx+edi], dl
dec edi
shr eax, 4
mov edx, eax
loop .16based_4bits
;现在put_int_buffer中已全是字符,打印之前,
;把高位连续的字符去掉,比如把字符000123变成123
.ready_to_print:
inc edi ; 此时edi退减为-1(0xffffffff),加1使其为0
.skip_prefix_0:
cmp edi,8 ; 若已经比较第9个字符了,表示待打印的字符串为全0
je .full0
;找出连续的0字符, edi做为非0的最高位字符的偏移
.go_on_skip:
mov cl, [put_int_buffer+edi]
inc edi
cmp cl, '0'
je .skip_prefix_0 ; 继续判断下一位字符是否为字符0(不是数字0)
dec edi ;edi在上面的inc操作中指向了下一个字符,若当前字符不为'0',要恢复edi指向当前字符
jmp .put_each_num
.full0:
mov cl,'0' ; 输入的数字为全0时,则只打印0
.put_each_num:
push ecx ; 此时cl中为可打印的字符
call put_char
add esp, 4
inc edi ; 使edi指向下一个字符
mov cl, [put_int_buffer+edi] ; 获取下一个字符到cl寄存器
cmp edi,8
jl .put_each_num
popad
ret
;------------------------ put_char -----------------------------
;功能描述:把栈中的1个字符写入光标所在处
;-------------------------------------------------------------------
global put_char
put_char:
pushad ;备份32位寄存器环境
;需要保证gs中为正确的视频段选择子,为保险起见,每次打印时都为gs赋值
mov ax, SELECTOR_VIDEO ; 不能直接把立即数送入段寄存器
mov gs, ax
;;;;;;;;; 获取当前光标位置 ;;;;;;;;;
;先获得高8位
mov dx, 0x03d4 ;索引寄存器
mov al, 0x0e ;用于提供光标位置的高8位
out dx, al
mov dx, 0x03d5 ;通过读写数据端口0x3d5来获得或设置光标位置
in al, dx ;得到了光标位置的高8位
mov ah, al
;再获取低8位
mov dx, 0x03d4
mov al, 0x0f
out dx, al
mov dx, 0x03d5
in al, dx
;将光标存入bx
mov bx, ax
;下面这行是在栈中获取待打印的字符
mov ecx, [esp + 36] ;pushad压入4×8=32字节,加上主调函数的返回地址4字节,故esp+36字节
cmp cl, 0xd ;CR是0x0d,LF是0x0a
jz .is_carriage_return
cmp cl, 0xa
jz .is_line_feed
cmp cl, 0x8 ;BS(backspace)的asc码是8
jz .is_backspace
jmp .put_other
;;;;;;;;;;;;;;;;;;
.is_backspace:
;;;;;;;;;;;; backspace的一点说明 ;;;;;;;;;;
; 当为backspace时,本质上只要将光标移向前一个显存位置即可.后面再输入的字符自然会覆盖此处的字符
; 但有可能在键入backspace后并不再键入新的字符,这时在光标已经向前移动到待删除的字符位置,但字符还在原处,
; 这就显得好怪异,所以此处添加了空格或空字符0
dec bx
shl bx,1
mov byte [gs:bx], 0x20 ;将待删除的字节补为0或空格皆可
inc bx
mov byte [gs:bx], 0x07
shr bx,1
jmp set_cursor
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.put_other:
shl bx, 1 ; 光标位置是用2字节表示,将光标值乘2,表示对应显存中的偏移字节
mov [gs:bx], cl ; ascii字符本身
inc bx
mov byte [gs:bx],0x07 ; 字符属性
shr bx, 1 ; 恢复老的光标值
inc bx ; 下一个光标值
cmp bx, 2000
jl set_cursor ; 若光标值小于2000,表示未写到显存的最后,则去设置新的光标值
; 若超出屏幕字符数大小(2000)则换行处理
.is_line_feed: ; 是换行符LF(\n)
.is_carriage_return: ; 是回车符CR(\r)
; 如果是CR(\r),只要把光标移到行首就行了。
xor dx, dx ; dx是被除数的高16位,清0.
mov ax, bx ; ax是被除数的低16位.
mov si, 80 ; 由于是效仿linux,linux中\n便表示下一行的行首,所以本系统中,
div si ; 把\n和\r都处理为linux中\n的意思,也就是下一行的行首。
sub bx, dx ; 光标值减去除80的余数便是取整
; 以上4行处理\r的代码
.is_carriage_return_end: ; 回车符CR处理结束
add bx, 80
cmp bx, 2000
.is_line_feed_end: ; 若是LF(\n),将光标移+80便可。
jl set_cursor
;屏幕行范围是0~24,滚屏的原理是将屏幕的1~24行搬运到0~23行,再将第24行用空格填充
.roll_screen: ; 若超出屏幕大小,开始滚屏
cld
mov ecx, 960 ; 一共有2000-80=1920个字符要搬运,共1920*2=3840字节.一次搬4字节,共3840/4=960次
mov esi, 0xc00b80a0 ; 第1行行首
mov edi, 0xc00b8000 ; 第0行行首
rep movsd
;;;;;;;将最后一行填充为空白
mov ebx, 3840 ; 最后一行首字符的第一个字节偏移= 1920 * 2
mov ecx, 80 ;一行是80字符(160字节),每次清理1字符(2字节),一行需要移动80次
.cls:
mov word [gs:ebx], 0x0720 ;0x0720是黑底白字的空格键
add ebx, 2
loop .cls
mov bx,1920 ;将光标值重置为1920,最后一行的首字符.
global set_cursor:
set_cursor:
;将光标设为bx值
;;;;;;; 1 先设置高8位 ;;;;;;;;
mov dx, 0x03d4 ;索引寄存器
mov al, 0x0e ;用于提供光标位置的高8位
out dx, al
mov dx, 0x03d5 ;通过读写数据端口0x3d5来获得或设置光标位置
mov al, bh
out dx, al
;;;;;;; 2 再设置低8位 ;;;;;;;;;
mov dx, 0x03d4
mov al, 0x0f
out dx, al
mov dx, 0x03d5
mov al, bl
out dx, al
.put_char_done:
popad
ret
global cls_screen:
cls_screen: ; 连着set_cursor
pushad ; 用户态不允许访问显存 只能由中断后进入内核态 故此为系统调用
mov ax,SELECTOR_VIDEO ; ax做中转
mov gs,ax ; 先放到gs里面 进入中断后再
mov ebx,0
mov ecx,80*25 ;清屏幕
.cls:
mov word [gs:ebx],0x720 ;黑底白字空格键
add ebx,2 ;一次两字节
loop .cls
mov ebx,0
jmp set_cursor
编写完的stdio-kernel.c
#include "stdio-kernel.h"
#include "stdint.h"
#include "stdio.h"
#include "console.h"
void printk(const char* format, ...)
{
va_list args;
va_start(args,format);
char buf[1024] = {0};
vsprintf(buf,format,args);
va_end(args);
console_put_str(buf);
}
void sys_putchar(const char chr)
{
console_put_char(chr);
}
编写完的stdio-kernel.h
#ifndef __LIB__STDIO_KERNEL_H
#define __LIB__STDIO_KERNEL_H
void printk(const char* format, ...);
void sys_putchar(const char chr);
#endif
lib/user相关文件
编写完的syscall.c
#include "syscall.h"
#define _syscall0(NUMBER) ({ \
int retval; \
asm volatile ("int $0x80" : "=a"(retval) : "a"(NUMBER) : "memory"); retval; \
})
#define _syscall1(NUMBER, ARG1) ({ \
int retval; \
asm volatile ("int $0x80" : "=a"(retval) : "a"(NUMBER) , "b"(ARG1) : "memory"); retval; \
})
#define _syscall2(NUMBER, ARG1, ARG2) ({ \
int retval; \
asm volatile ("int $0x80" : "=a"(retval) : "a"(NUMBER) , "b"(ARG1) , "c"(ARG2): "memory"); retval; \
})
#define _syscall3(NUMBER, ARG1, ARG2, ARG3) ({ \
int retval; \
asm volatile ("int $0x80" : "=a"(retval) : "a"(NUMBER) , "b"(ARG1) , "c"(ARG2), "d"(ARG3): "memory"); retval; \
})
uint32_t getpid(void)
{
return _syscall0(SYS_GETPID);
}
uint32_t write(int fd,const void* buf,int count)
{
return _syscall3(SYS_WRITE,fd,buf,count);
}
void* malloc(uint32_t size)
{
return _syscall1(SYS_MALLOC,size);
}
void free(void* ptr)
{
return _syscall1(SYS_FREE,ptr);
}
int32_t fork(void)
{
return _syscall0(SYS_FORK);
}
int32_t read(int32_t fd,void* buf,uint32_t count)
{
return _syscall3(SYS_READ,fd,buf,count);
}
void putchar(const char chr)
{
return _syscall1(SYS_PUTCHAR,chr);
}
void clear(void)
{
return _syscall0(SYS_CLEAR);
}
char* getcwd(char* buf,uint32_t size)
{
return (char*)_syscall2(SYS_GETCWD,buf,size);
}
int32_t open(char* pathname,uint8_t flag)
{
return _syscall2(SYS_OPEN,pathname,flag);
}
int32_t close(int32_t fd)
{
return _syscall1(SYS_CLOSE,fd);
}
int32_t lseek(int32_t fd,int32_t offset,uint8_t whence)
{
return _syscall3(SYS_LSEEK,fd,offset,whence);
}
int32_t unlink(const char* pathname)
{
return _syscall1(SYS_UNLINK,pathname);
}
int32_t mkdir(const char* pathname)
{
return _syscall1(SYS_MKDIR,pathname);
}
struct dir* opendir(const char* name)
{
return (struct dir*)_syscall1(SYS_OPENDIR,name);
}
int32_t closedir(struct dir* dir)
{
return _syscall1(SYS_CLOSEDIR,dir);
}
int32_t rmdir(const char* pathname)
{
return _syscall1(SYS_RMDIR,pathname);
}
struct dir_entry* readdir(struct dir* dir)
{
return (struct dir_entry*)_syscall1(SYS_READDIR,dir);
}
void rewinddir(struct dir* dir)
{
_syscall1(SYS_REWINDDIR,dir);
}
int32_t stat(const char* path,struct stat* buf)
{
return _syscall2(SYS_STAT,path,buf);
}
int32_t chdir(const char* path)
{
return _syscall1(SYS_CHDIR,path);
}
void ps(void)
{
return _syscall0(SYS_PS);
}
int32_t execv(const char* path,const char* argv[])
{
return _syscall2(SYS_EXECV,path,argv);
}
编写完的syscall.h
#ifndef __LIB_USER_SCSCALL_H
#define __LIB_USER_SCSCALL_H
#include "stdint.h"
#include "../fs/file.h"
enum SYSCALL_NR
{
SYS_GETPID,
SYS_WRITE,
SYS_MALLOC,
SYS_FREE,
SYS_FORK,
SYS_READ,
SYS_PUTCHAR,
SYS_CLEAR,
SYS_GETCWD,
SYS_OPEN,
SYS_CLOSE,
SYS_LSEEK,
SYS_UNLINK,
SYS_MKDIR,
SYS_OPENDIR,
SYS_CLOSEDIR,
SYS_CHDIR,
SYS_RMDIR,
SYS_READDIR,
SYS_REWINDDIR,
SYS_STAT,
SYS_PS,
SYS_EXECV
};
uint32_t getpid(void);
uint32_t write(int fd,const void* buf,int count);
void* malloc(uint32_t size);
void free(void* ptr);
int32_t fork(void);
int32_t read(int32_t fd,void* buf,uint32_t count);
void putchar(const char chr);
void clear(void);
char* getcwd(char* buf,uint32_t size);
int32_t open(char* pathname,uint8_t flag);
int32_t close(int32_t fd);
int32_t lseek(int32_t fd,int32_t offset,uint8_t whence);
int32_t unlink(const char* pathname);
int32_t mkdir(const char* pathname);
struct dir* opendir(const char* name);
int32_t closedir(struct dir* dir);
int32_t rmdir(const char* pathname);
struct dir_entry* readdir(struct dir* dir);
void rewinddir(struct dir* dir);
int32_t stat(const char* path,struct stat* buf);
int32_t chdir(const char* path);
void ps(void);
int32_t execv(const char* path,const char* argv[]);
#endif
lib直接相关子文件
编写完的stdint.h
#ifndef __LIB_STDINT_H
#define __LIB_STDINT_H
#define true 1
#define false 0
#define NULL 0
typedef int bool;
typedef signed char int8_t;
typedef signed short int int16_t;
typedef signed int int32_t;
typedef signed long long int int64_t;
typedef unsigned char uint8_t;
typedef unsigned short int uint16_t;
typedef unsigned int uint32_t;
typedef unsigned long long int uint64_t;
#endif
编写完的stdio.c
#include "stdio.h"
#include "stdint.h"
#include "string.h"
#include "syscall.h"
void itoa(uint32_t value,char** buf_ptr_addr,uint8_t base)
{
uint32_t m = value % base;
uint32_t i = value / base;
if(i)
itoa(i,buf_ptr_addr,base);
if(m < 10)
*((*buf_ptr_addr)++) = m + '0';
else
*((*buf_ptr_addr)++) = m + 'A' - 10;
}
uint32_t vsprintf(char* str,const char* format,va_list ap)
{
char* buf_ptr = str;
const char* index_ptr = format;
char index_char = *index_ptr;
int32_t arg_int;
char* arg_str;
while(index_char)
{
if(index_char != '%')
{
*(buf_ptr++) = index_char;
index_char = *(++index_ptr);
continue;
}
index_char = *(++index_ptr);
switch(index_char)
{
case 's':
arg_str = va_arg(ap,char*);
strcpy(buf_ptr,arg_str);
buf_ptr += strlen(arg_str);
index_char = *(++index_ptr);
break;
case 'x':
arg_int = va_arg(ap,int);
itoa(arg_int,&buf_ptr,16);
index_char = *(++index_ptr);
break;
case 'd':
arg_int = va_arg(ap,int);
if(arg_int < 0)
{
arg_int = 0 - arg_int;
*(buf_ptr++) = '-';
}
itoa(arg_int,&buf_ptr,10);
index_char = *(++index_ptr);
break;
case 'c':
*(buf_ptr++) = va_arg(ap,char);
index_char = *(++index_ptr);
}
}
return strlen(str);
}
uint32_t printf(const char* format, ...)
{
va_list args;
va_start(args,format);
char buf[1024] = {0};
vsprintf(buf,format,args);
va_end(args);
return write(1,buf,strlen(buf));
}
uint32_t sprintf(char* _des,const char* format, ...)
{
va_list args;
uint32_t retval;
va_start(args,format);
retval = vsprintf(_des,format,args);
va_end(args);
return retval;
}
编写完的stdio.h
#ifndef __LIB__STDIO_H
#define __LIB__STDIO_H
#include "stdint.h"
#define va_start(ap,v) ap = (va_list)&v
#define va_arg(ap,t) *((t*)(ap +=4))
#define va_end(ap) ap = NULL
typedef void* va_list;
void itoa(uint32_t value,char** buf_ptr_addr,uint8_t base);
uint32_t vsprintf(char* str,const char* format,va_list ap);
uint32_t sprintf(char* _des,const char* format, ...);
uint32_t printf(const char* format, ...);
#endif
编写完的string.c
#include "string.h"
#include "debug.h"
#include "global.h"
void memset(void* dst_,uint8_t value,uint32_t size)
{
ASSERT(dst_ != NULL);
uint8_t* dst = (uint8_t*) dst_;
while((size--) > 0)
*(dst++) = value;
return;
}
void memcpy(void* dst_,const void* src_,uint32_t size)
{
ASSERT(dst_ != NULL && src_ != NULL);
uint8_t* dst = dst_;
const uint8_t* src = src_;
while((size--) > 0)
*(dst++) = *(src++);
return;
}
int memcmp(const void* a_,const void* b_, uint32_t size)
{
const char* a = a_;
const char* b = b_;
ASSERT(a != NULL || b != NULL);
while((size--) > 0)
{
if(*a != *b) return (*a > *b) ? 1 : -1;
++a,++b;
}
return 0;
}
char* strcpy(char* dsc_,const char* src_)
{
ASSERT(dsc_ != NULL && src_ != NULL);
char* dsc = dsc_;
while((*(dsc_++) = *(src_++) ));
return dsc;
}
uint32_t strlen(const char* str)
{
ASSERT(str != NULL);
const char* ptr = str;
while(*(ptr++));
return (ptr - str - 1);
}
int8_t strcmp(const char* a,const char* b)
{
ASSERT(a != NULL && b != NULL);
while(*a && *a == *b)
{
a++,b++;
}
return (*a < *b) ? -1 : (*a > *b) ;
}
char* strchr(const char* str,const char ch)
{
ASSERT(str != NULL);
while(*str != 0)
{
if(*str == ch) return (char*)str;
++str;
}
return NULL;
}
char* strrchr(const char* str,const uint8_t ch)
{
ASSERT(str != NULL);
char* last_chrptr = NULL;
while(*str != 0)
{
if(ch == *str) last_chrptr = (char*)str;
str++;
}
return last_chrptr;
}
char* strcat(char* dsc_,const char* src_)
{
ASSERT(dsc_ != NULL && src_ != NULL);
char* str = dsc_;
while(*(str++));
str--;
while(*(str++) = *(src_++));
return dsc_;
}
char* strchrs(const char* str,uint8_t ch)
{
ASSERT(str != NULL);
uint32_t ch_cnt = 0;
while(*str)
{
if(*str == ch) ++ch_cnt;
++str;
}
return ch_cnt;
}
编写完的string.h
#ifndef __LIB_STRING_H
#define __LIB_STRING_H
#include "stdint.h"
void memset(void* dst_,uint8_t value,uint32_t size);
void memcpy(void* dst_,const void* src_,uint32_t size);
int memcmp(const void* a_,const void* b_, uint32_t size);
char* strcpy(char* dsc_,const char* src_);
uint32_t strlen(const char* str);
int8_t strcmp(const char* a,const char* b);
char* strchr(const char* str,const char ch);
char* strrchr(const char* str,const uint8_t ch);
char* strcat(char* dsc_,const char* src_);
char* strchrs(const char* str,uint8_t ch);
#endif