Tôi đang cố gắng in một cái gì đó trên màn hình bằng chức năng in của mình.Truyền mảng ký tự làm tham số (mã hạt nhân C)
tôi đã vấp vào một vấn đề nhỏ - khi tôi vượt qua các mảng nhân vật như thế này:
char s[] = "abc";
print(s);
Nó hoạt động tốt, nhưng khi tôi gọi nó là như thế này không có hiệu lực.
print("abc");
Đây là khai báo hàm của tôi
//print function
void print(char* message);
Am tôi thiếu cái gì? printf hoạt động theo cùng một cách, và bạn có thể truyền chuỗi theo cách thứ hai.
EDIT:
định nghĩa
void print_at(char* message, int col, int row){
if(col >= 0 && row >= 0){
set_cursor(get_screen_offset(col,row));
}
int i = 0;
while(message[i] != 0){
print_char(message[i++],-1,-1,WHITE_ON_BLACK);
}
}
void print(char* message){
print_at(message, -1,-1);
}
EDIT2: objdump của kernel.o
void start(){
clear_screen();
char s[] = "abc";
print("abc");
print(s);
while(1);
}
Tháo lắp phần .text:
00000000 <_start>:
0: 55 push ebp
1: 89 e5 mov ebp,esp
3: 83 ec 28 sub esp,0x28
6: e8 00 00 00 00 call b <_start+0xb> //clear_screen()
b: c7 45 f4 61 62 63 00 mov DWORD PTR [ebp-0xc],0x636261 //"bca"
12: c7 04 24 00 00 00 00 mov DWORD PTR [esp],0x0
19: e8 00 00 00 00 call 1e <_start+0x1e> //print()
1e: 8d 45 f4 lea eax,[ebp-0xc]
21: 89 04 24 mov DWORD PTR [esp],eax
24: e8 00 00 00 00 call 29 <_start+0x29> //print()
29: eb fe jmp 29 <_start+0x29>
2b: 90 nop
EDIT3:
Vì đây có thể là một cái gì đó với cách tôi initilising các môi trường, đây là 2 file đáp trả:
pmode.asm -initializes phân đoạn, và nhảy để bắt đầu của kernel
[bits 16]
switch_to_pm:
cli ; switch interuppts off
lgdt [gdt_descriptor] ; load global descriptor table
mov eax, cr0 ; set control registers first bit to protected mode
or eax, 0x1
mov cr0, eax
jmp CODE_SEG:init_pm ;flush cache by far jump
[bits 32]
init_pm:
mov ax, DATA_SEG
mov ds, ax
mov ss, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ebp, 0x90000
mov esp, ebp
call BEGIN_PM
đây là cách tôi tạo gdt:
; GDT
gdt_start:
gdt_null: ; the mandatory null descriptor
dd 0x0 ; ' dd ' means define double word (i.e. 4 bytes)
dd 0x0
gdt_code: ; the code segment descriptor
; base =0 x0 , limit =0 xfffff ,
; 1 st flags : (present)1 (privilege)00 (descriptor type)1 -> 1001 b
; type flags : (code)1 (conforming)0 (readable)1 (accessed)0 -> 1010 b
; 2 nd flags : (granularity)1 (32- bit default)1 (64- bit seg)0 (AVL)0 -> 1100 b
dw 0xffff ; Limit (bits 0-15)
dw 0x0 ; Base (bits 0-15)
db 0x0 ; Base (bits 16-23)
db 10011010b ; 1 st flags , type flags
db 11001111b ; 2 nd flags , Limit (bits 16-19)
db 0x0 ; Base (bits 24-31)
gdt_data: ; the data segment descriptor
; Same as code segment except for the type flags :
; type flags : (code)0 (expand down)0 (writable)1 (accessed)0 -> 0010 b
dw 0xffff ; Limit (bits 0-15)
dw 0x0 ; Base (bits 0-15)
db 0x0 ; Base (bits 16-23)
db 10010010b ; 1 st flags , type flags
db 11001111b ; 2 nd flags , Limit (bits 16-19)
db 0x0 ; Base (bits 24-31)
gdt_end: ; The reason for putting a label at the end of the
; GDT is so we can have the assembler calculate
; the size of the GDT for the GDT decriptor (below)
; GDT descriptior
gdt_descriptor:
dw gdt_end - gdt_start - 1 ; Size of our GDT , always less one
; of the true size
dd gdt_start ; Start address of our GDT
; Define some handy constants for the GDT segment descriptor offsets , which
; are what segment registers must contain when in protected mode. For example ,
; when we set DS = 0 x10 in PM , the CPU knows that we mean it to use the ; segment described at offset 0 x10 (i.e. 16 bytes) in our GDT , which in our
; case is the DATA segment (0 x0 -> NULL ; 0 x08 -> CODE ; 0 x10 -> DATA)
CODE_SEG equ gdt_code - gdt_start
DATA_SEG equ gdt_data - gdt_start
Và chức năng của bạn ** được xác định ** (i. E. Implement)? –
@ H2CO3 đã thêm định nghĩa –
bạn nên sử dụng 'const char *', nhưng điều đó có lẽ không liên quan. – Dave