$ ifconfig eth100 > msg.log 2>&1
can be shortened like that:
$ ifconfig eth100 &> msg.log
or
$ ifconfig eth100 >& msg.log
【Reference】
Bash Reference Manual
What a fascinating Linux it is!
$ ifconfig eth100 > msg.log 2>&1
$ ifconfig eth100 &> msg.log
$ ifconfig eth100 >& msg.log
void swap(int *a, int *b)
{
int tmp;
tmp = *a;
*a = *b;
*b = tmp;
}
void swap(int *a, int *b)
{
if(*a != *b) {
*a = *a ^ *b;
*b = *a ^ *b;
*a = *a ^ *b;
}
}
#include <stdio.h>
void swap(int *a, int *b)
{
if(*a != *b)
*a ^= *b ^= *a ^= *b;
}
int main(void)
{
int a = 11, b = 3;
printf("===== before swapping =====\n");
printf("a: %d, b: %d\n", a, b);
swap(&a, &b);
printf("===== after swapping =====\n");
printf("a: %d, b: %d\n", a, b);
return 0;
}
1. 硬體暫存器,如狀態暫存器。
2. 多執行緒所共用的全域變數。
3. 中斷服務函式 (Interrupt Service Rountie,ISR)所使用的全域變數。
#include <stdio.h>
int square(volatile int *var)
{
return *var **var;
}
int main(void)
{
int var = 5;
printf("result: %d\n", square(&var));
return 0;
}
#include <stdio.h>
int square(volatile int *var)
{
int local_var = *var;
return local_var * local_var;
}
int main(void)
{
int var = 5;
printf("result: %d\n", square(&var));
return 0;
}
void *memory_align(unsigned int size, unsigned int aligned_size)
{
void *ptr;
unsigned int mask = ~(aligned_size -1);
if((ptr = malloc(sizeof(size + (aligned_size - 1)))) == NULL) {
perror("memory allocation failed");
return NULL;
}
ptr = (void *) ((unsigned int) (ptr + (aligned_size - 1)) & mask);
return ptr;
}
unsigned int mask = ~(aligned_size -1);ptr = malloc(sizeof(size + (aligned_size - 1)))ptr = (void *) ((unsigned int) (ptr + (aligned_size - 1)) & mask);$ sudo chown -R adrian.adrian /usr/
結果導致使用sudo會有底下的問題:$ sudo su
sudo: must be setuid root
這下可high了, Ubuntu在安裝的時候並沒有讓管理者設定root密碼, 所以無法使用root登入, 沒有root權限什麼事都不能做啊! 底下解決方式:-rwxr-xr-x 2 adrian adrian 147872 2010-09-01 04:39 /usr/bin/sudo
# chwon root:root /usr/bin/sudo
# chmod 4755 /usr/bin/sudo
# reboot
$ sudo chown root.root /usr/
/* Jump to protected-mode OS code *
* ljmpl prototype: *
* ljmpl segment_selector_of_CS offset */
ljmpl $SegSelectorCode32, $0
/* Load LDT selector */
mov $(SegSelectorLDT), %ax
/* Load LDT selector in GDT to LDT register */
lldt %ax
/* Jump to code segment in LDT */
lcall $(SegSelectorLDTCode32), $0
pushl $(SegSelectorStackR3)
pushl $(TopOfStackR3)
pushl $(SegSelectorCodeR3)
pushl $0
lret
LABEL_TSS:
.4byte 0 /* Previous Task Link */
.4byte TopOfStackR0 /* ESP0 */
.4byte SegSelectorStackR0 /* SS0 */
.4byte 0 /* ESP1 */
.4byte 0 /* SS1 */
.4byte 0 /* ESP2 */
.4byte 0 /* SS2 */
.4byte 0 /* CR3 (PDBR) */
.4byte 0 /* EIP */
.4byte 0 /* EFLAGS */
.4byte 0 /* EAX */
.4byte 0 /* ECX */
.4byte 0 /* EDX */
.4byte 0 /* EBX */
.4byte 0 /* ESP */
.4byte 0 /* EBP */
.4byte 0 /* ESI */
.4byte 0 /* EDI */
.4byte 0 /* ES */
.4byte 0 /* CS */
.4byte 0 /* SS */
.4byte 0 /* DS */
.4byte 0 /* FS */
.4byte 0 /* GS */
.4byte 0 /* LDT Segment Selector */
.2byte 0 /* Reserved */
.2byte (. - LABEL_TSS + 2) /* I/O Map Base Address */
.set TSSLen, (. - LABEL_TSS)
在此,特別對特權等級轉換做進一步解釋,以便讓讀者了解為什麼只要設定ESP0與SS0欄位即可。當存取目的程式區段 (Destination Code Segment)是被允許的,處理器便會根據Call Gate Descriptor的Segment Selector欄位找出對應的程式區段,如果又涉及特權等級轉換,處理器會將原本使用中的堆疊切換至目標特權等級的堆疊。舉例來說,假設目前程式區段運行於Ring 3,處理器便使用Ring 3的堆疊,當使用Call Gate欲轉換至Ring 0的程式區段。如果此要求是被允許的,則處理器會跳至Ring 0的程式區段並使用Ring 0的堆疊,因此程式設計員必須先設定Ring 0堆疊 (ESP0與SS0),這就是為什麼必須設定TSS的ESP與SS0欄位的原因。 /* os.S
*
*/
#include "pm.h"
.code16
.text
jmp os_main
# Segment descritors for GDT
LABEL_GDT_NULL: SEG_DESC 0, 0, 0
LABEL_GDT_CODE: SEG_DESC 0, (PECode32Len - 1), (DESC_ATTR_TYPE_CD_ER | DESC_ATTR_D)
LABEL_GDT_DATA: SEG_DESC 0, (DataLen - 1), (DESC_ATTR_TYPE_CD_RW)
LABEL_GDT_VIDEO: SEG_DESC 0xB8000, 0xFFFF, (DESC_ATTR_TYPE_CD_RW)
LABEL_GDT_LDT: SEG_DESC 0, (LDTLen - 1), (DESC_ATTR_TYPE_LDT)
LABEL_GDT_CG_CODE: SEG_DESC 0, (CG_CODE32_LEN - 1), (DESC_ATTR_TYPE_CD_ER | DESC_ATTR_D)
LABEL_GDT_CG: CALL_GATE SegSelectorCGCODE, 0, 0, (GATE_CG_ATTR)
# The length of GDT
.set GdtLen, (. - LABEL_GDT_NULL)
# Segment selectors
.set SegSelectorCode32, (LABEL_GDT_CODE - LABEL_GDT_NULL)
.set SegSelectorData, (LABEL_GDT_DATA - LABEL_GDT_NULL)
.set SegSelectorVideo, (LABEL_GDT_VIDEO - LABEL_GDT_NULL)
.set SegSelectorLDT, (LABEL_GDT_LDT - LABEL_GDT_NULL)
.set SegSelectorCGCODE, (LABEL_GDT_CG_CODE - LABEL_GDT_NULL)
.set SegSelectorCG, (LABEL_GDT_CG - LABEL_GDT_NULL)
# data segment
LABEL_DATA:
Msg1: .ascii "Welcome to Protect mode in GDT.\0"
Msg2: .ascii "Welcome to Protect mode in LDT.\0"
Msg3: .ascii "Welcome to Protect mode through Call Gate.\0"
.set Msg1Offset, (Msg1 - LABEL_DATA)
.set Msg2Offset, (Msg2 - LABEL_DATA)
.set Msg3Offset, (Msg3 - LABEL_DATA)
.set DataLen, (. - LABEL_DATA)
# GDTR pointer
LABEL_GDTR:
.2byte (GdtLen - 1) # Limit field
.4byte 0 # base field
# LDT information
LABEL_LDT:
LABEL_LDT_ENTRY: SEG_DESC 0, (LDT_CODE32_LEN - 1), (DESC_ATTR_TYPE_CD_E | DESC_ATTR_D)
# length of LDT
.set LDTLen, (. - LABEL_LDT)
# LDT selector
.set SegSelectorLDTCode32, (LABEL_LDT_ENTRY - LABEL_LDT + SA_TIL)
# real-mode OS code
os_main:
mov %cs, %ax
mov %ax, %ds
mov %ax, %ss
mov %ax, %es
/* Set gdt for code segment */
InitSegDescriptor LABEL_PE_CODE32, LABEL_GDT_CODE
InitSegDescriptor LABEL_DATA, LABEL_GDT_DATA
InitSegDescriptor LABEL_LDT, LABEL_GDT_LDT
InitSegDescriptor LABEL_PE_LDT_CODE32, LABEL_LDT_ENTRY
InitSegDescriptor LABEL_PE_CG_CODE32, LABEL_GDT_CG_CODE
/* Set GDTR */
xor %ax, %ax
mov %cs, %ax
shl $4, %eax
addl $LABEL_GDT_NULL, %eax
movl %eax, (LABEL_GDTR + 2)
/* Enable A20 line */
xor %ax, %ax
in $0x92, %al
or $2, %al
out %al, $0x92
cli
/* Load the GDT base address and limit from memory into the GDTR register */
lgdt LABEL_GDTR
/* Enable protect mode */
movl %cr0, %eax
orl $1, %eax
movl %eax, %cr0
/* Jump to protected-mode OS code */
ljmp $SegSelectorCode32, $0
LABEL_PE_CG_CODE32:
.code32
mov $(SegSelectorData), %ax
mov %ax, %ds
mov $(SegSelectorVideo), %ax
mov %ax, %gs
xorl %esi, %esi
xorl %edi, %edi
movl $Msg3Offset, %esi
movl $((80 * 11 + 0) * 2), %edi
movb $0xC, %ah
cg_dump_str:
lodsb
andb %al, %al
jz cg_fin
mov %ax, %gs:(%edi)
addl $2, %edi
jmp cg_dump_str
cg_fin:
lret
.set CG_CODE32_LEN, (. - LABEL_PE_CG_CODE32)
LABEL_PE_LDT_CODE32:
.code32
# invoke a procedure call throught a call-gate.
lcall $(SegSelectorCG), $0
mov $(SegSelectorData), %ax
mov %ax, %ds
mov $(SegSelectorVideo), %ax
mov %ax, %gs
xorl %esi, %esi
xorl %edi, %edi
movl $Msg2Offset, %esi
movl $((80 * 13 + 0) * 2), %edi
movb $0xC, %ah
ldt_dump_str:
lodsb
andb %al, %al
jz ldt_fin
mov %ax, %gs:(%edi)
addl $2, %edi
jmp ldt_dump_str
ldt_fin:
jmp .
.set LDT_CODE32_LEN, (. - LABEL_PE_LDT_CODE32)
# protected-mode OS code in GDT
LABEL_PE_CODE32:
.code32
/* Load data segment selector */
mov $(SegSelectorData), %ax
mov %ax, %ds
/* Load Video segment selector */
mov $(SegSelectorVideo), %ax
mov %ax, %gs
/* Output the data */
xorl %esi, %esi
xorl %edi, %edi
movl $Msg1Offset, %esi
movl $((80 * 10 + 0) * 2), %edi
movb $0xC, %ah
dump_str:
lodsb
andb %al, %al
jz fin
mov %ax, %gs:(%edi)
addl $2, %edi
jmp dump_str
fin:
/* Load LDT selector */
mov $(SegSelectorLDT), %ax
/* Load LDT selector in GDT to LDT register */
lldt %ax
/* Jump to code segment in LDT */
ljmp $(SegSelectorLDTCode32), $0
.set PECode32Len, (. - LABEL_PE_CODE32)
.ascii "Welcome to OS context!"
.byte 0
.org 0x400, 0x41 # fill characters with 'A'. Sector 2
/* pm.h
*
* Adrian Huang (adrianhuang0701@gmail.com)
*/
.macro SEG_DESC Base, Limit, Attr
.2byte (\Limit & 0xFFFF)
.2byte (\Base & 0xFFFF)
.byte ((\Base >> 16) & 0xFF)
.2byte ((\Attr & 0xF0FF) | ((\Limit >> 8) & 0x0F00))
.byte ((\Base >> 24) & 0xFF)
.endm
.macro InitSegDescriptor OFFSET GDT_SEG_ADDR
xor %ax, %ax
mov %cs, %ax
shl $4, %eax
addl $(\OFFSET), %eax
movw %ax, (\GDT_SEG_ADDR + 2)
shr $16, %eax
movb %al, (\GDT_SEG_ADDR + 4)
movb %ah, (\GDT_SEG_ADDR + 7)
.endm
.macro CALL_GATE SegSelector, Offset, ParamCount, Attr
.2byte (\Offset & 0xFFFF)
.2byte (\SegSelector)
.byte (\ParamCount)
.byte (\Attr)
.2byte ((\Offset >> 16) & 0xFFFF)
.endm
.set DESC_ATTR_TYPE_LDT, 0x82 /* LDT Segment */
.set DESC_ATTR_TYPE_CG, 0x8C /* Call-Gate Segment */
.set DESC_ATTR_TYPE_CD_ER, 0x9A /* Code segment with Execute/Read */
.set DESC_ATTR_TYPE_CD_E, 0x98 /* Code segment with Execute Only */
.set DESC_ATTR_TYPE_CD_RW, 0x92 /* Data segment with R/W */
.set DESC_ATTR_D, 0x4000 /* 32-bit segment */
/* Selector Attribute */
.set SA_TIL, 0x4
.set SA_RPL0, 0x0
.set SA_RPL1, 0x1
.set SA_RPL2, 0x2
.set SA_RPL3, 0x3
/* The attribute of call gate */
.set GATE_CG_ATTR, 0x8C
LD=ld
CC=gcc
all: boot_loader.bin
boot_loader.bin: boot_loader.o os.o
${LD} -Ttext=0x7C00 -s $< -o $@ --oformat binary ${LD} -Ttext=0x0 -s os.o -o os.bin --oformat binary cat os.bin >> $@
boot_loader.o:
${CC} -c boot_loader.S
os.o:
${CC} -c os.S
clean:
rm -f boot_loader.o os.o os.bin boot_loader.bin
adrian@adrian-desktop:~/working/build_os/my_ex/blog/pe-call-gate-same-priv$ make clean all
rm -f boot_loader.o os.o os.bin boot_loader.bin
gcc -c boot_loader.S
gcc -c os.S
ld -Ttext=0x7C00 -s boot_loader.o -o boot_loader.bin --oformat binary
ld -Ttext=0x0 -s os.o -o os.bin --oformat binary
ld: warning: cannot find entry symbol _start; defaulting to 0000000000000000
cat os.bin >> boot_loader.bin
adrian@adrian-desktop:~/working/build_os/my_ex/blog/pe-call-gate-same-priv$
