兴复汉唐
镜像:https://leisurebamboo.wordpress.com/2023/10/05/tc1
兴复汉唐——Turbo C汉化浅析之一
原文在2005-4-25 发表于 http://www.aogosoft.com/bbs/view.asp?id=39189 ,现有增删。
"汉化"(Sinicization)暂定义为“函数名、变量名、宏名 能用汉字”。
竹闲的贴子,每行不超过43个字符,
从而言逾百行,令阅贴观众狂按 Page-Down,
在此深深致歉。
因为他的ie显示的是大字体,他自己阅贴时在
屏上每行真的不超过43个字符,以此小人之心
度诸位君子之腹,遂有此事。
言归正传,循例先说低版本的Turbo C汉化:
TC 1.0版的tcc.exe,长度为 16'9098字节。
在哈工大的论坛的下载链接上,它被揶揄为
"仅供老一辈程序员使用",
在网上搜索"TC 1.0"时连外国网页也不好找,
好像在www.coldyne.com上还有下载链接。
姑妄言之:
其编译部分为:
在 fgetc() 後,tcc.exe 在 ds:1aaa 始的《分枝枚举表》内,查了AL字符所对应case语句的分枝枚举值;再按照该枚举值,跳转到cs:4d 处相应的分枝去。
《分枝枚举表》以 ds:1aaa 始,内共有100h个word,取值从-19h(ffe7h)到0029h 不等,其详细内容为:
gbk码或big5码首字节对应的分枝枚举值,全落在该表的後半部分内,且均为-12h(ffeeh)。
(《分枝枚举表》的後半部分 位于tcc.exe的 第[2632A~26429]字节,共80h个字)
而 枚举值-12h相应的分枝在cs:020Ah,其case语句仅有11h字节,难以改写。若需汉化,祗好将《分枝枚举表》的後半部分,改作80h个“在表中常见的”fff6。
常见的枚举值-0Ah(fff6h),在分枝对应到cs:00A1h处,其编译部分为:
其中ds:4b57 开始为《ascii码对应属性表》,具体内容为:
汉化方法仍是将ascii80~FF的对应属性部分
(位于tcc.exe的第[29357h~293D6h]字节,原文为80h个字节,均为0),
换为80h dup(8h)。
以上所论皆是数据(data)。以下讨论代码(code),共须改动三处:
tcc 调用 fgetch(可能是 fgetch_1、fgetch_2、fgetch_3、fgetch_4)时:
至此,tcc.exe 1.0 版本汉化完毕。 函数名、变量名、宏名 均能用汉字。
但为便于日後tc编译链接,命名时请仍沿用下划线 或英文字母开头。
具体的asm,参阅https://sourceforge.net/projects/difc/files/turbo_c/1.0/
汉乃百族之长,唐为历朝之冠。当年中国在政治、军事、经济、文化等各方面均居世界前茅;
今日式微,我等後人不肖,编个程序连中文都不能用。
在此并非鼓吹连mov旨令、if关键字都得换成汉语,但若用1个中文变量也会引起编译错误,则起码可责其未考虑13亿人口的需求。
竹闲不自量力,推出TC汉化系列,冀可一振华夏之气。至于成败利钝,则非竹闲所能逆料也;
唯盼国人齐心戮力,重兴此尧唐的盛世,再睹我大汉的天威。
Turbo C 更高版本的汉化,敬请关注下期。(待续)
兴复汉唐——Turbo C汉化浅析之一
原文在2005-4-25 发表于 http://www.aogosoft.com/bbs/view.asp?id=39189 ,现有增删。
"汉化"(Sinicization)暂定义为“函数名、变量名、宏名 能用汉字”。
竹闲的贴子,每行不超过43个字符,
从而言逾百行,令阅贴观众狂按 Page-Down,
在此深深致歉。
因为他的ie显示的是大字体,他自己阅贴时在
屏上每行真的不超过43个字符,以此小人之心
度诸位君子之腹,遂有此事。
言归正传,循例先说低版本的Turbo C汉化:
TC 1.0版的tcc.exe,长度为 16'9098字节。
在哈工大的论坛的下载链接上,它被揶揄为
"仅供老一辈程序员使用",
在网上搜索"TC 1.0"时连外国网页也不好找,
好像在www.coldyne.com上还有下载链接。
姑妄言之:
其编译部分为:
cs:0024 | 9AB505xxxx | CALL far fgetc() ;//xxxx:05B5 |
cs:0029 | 8BF0 | MOV SI,AX |
cs:002B | 8BDE | MOV BX,SI |
cs:002D | 83C302 | ADD BX,02 |
cs:0030 | D1E3 | SHL BX,1 |
cs:0032 | 8B87A61A | MOV AX,[1AA6+BX] ;//此时 AX=分枝枚举值 |
cs:0036 | 8946FE | MOV [BP-02],AX |
cs:0039 | 2DE7FF | AX+=19h |
cs:003C | 3D1900 | CMP AX,0019 |
cs:003F | 7603 | JBE 0044 |
cs:0041 | E99600 | JMP 00DA |
cs:0044 | 8BD8 | MOV BX,AX |
cs:0046 | D1E3 | SHL BX,1 |
cs:0048 | 2EFFA74D00 | JMP CS:[004D+BX] ;//cs:[004D+(0019+fff6)*2]==00a1 |
《分枝枚举表》以 ds:1aaa 始,内共有100h个word,取值从-19h(ffe7h)到0029h 不等,其详细内容为:
dw ffee,ffee,ffee,ffee, ffee,ffee,ffee,ffee | ;00~07 |
dw ffee,fff7,ffec,fff7, fff7,fff7,ffee,ffee | ;08~0f |
dw ffee,ffee,ffee,ffee, ffee,ffee,ffee,ffee | ;10~17 |
dw ffee,ffee,ffe7,ffee, ffee,ffee,ffee,ffee | ;18~1f |
dw fff7,0000,fff4,fff3, ffee,ffff,fffe,fff2 | ;20~27 |
dw 0001,0002,fffd,fffc, 0008,fff1,fff0,fffb | ;28~2f |
dw fff5,fff5,fff5,fff5, fff5,fff5,fff5,fff5 | ;'0'~'7' |
dw fff5,fff5,001f,0007, ffef,fff8,ffed,001e | ;'8','9', 3a~3f |
dw ffee,fff6,fff6,fff6, fff6,fff6,fff6,fff6 | ;'@', 'A'~'G' |
dw fff6,fff6,fff6,fff6, fff6,fff6,fff6,fff6 | ;'H'~'O' |
dw fff6,fff6,fff6,fff6, fff6,fff6,fff6,fff6 | ;'P'~'W' |
dw fff6,fff6,fff6,0003, ffea,0004,fffa,fff6 | ;'X'~'Z', 5b~5f |
dw ffee,fff6,fff6,fff6, fff6,fff6,fff6,fff6 | ;60, 'a'~'g' |
dw fff6,fff6,fff6,fff6, fff6,fff6,fff6,fff6 | ;'h'~'o' |
dw fff6,fff6,fff6,fff6, fff6,fff6,fff6,fff6 | ;'p'~'w' |
dw fff6,fff6,fff6,0005, fff9,0006,0029,ffee | ;'x'~'z', 7b~7f |
dw 80 dup(ffee) |
gbk码或big5码首字节对应的分枝枚举值,全落在该表的後半部分内,且均为-12h(ffeeh)。
(《分枝枚举表》的後半部分 位于tcc.exe的 第[2632A~26429]字节,共80h个字)
而 枚举值-12h相应的分枝在cs:020Ah,其case语句仅有11h字节,难以改写。若需汉化,祗好将《分枝枚举表》的後半部分,改作80h个“在表中常见的”fff6。
常见的枚举值-0Ah(fff6h),在分枝对应到cs:00A1h处,其编译部分为:
cs:00A1 | C6061A5F00 | MOV byte[5F1A],00 |
... | ||
cs:00BB | F684574B02 | TEST byte[SI+4B57],2 |
cs:00C0 | 7574 | JNZ 0136 |
cs:00C2 | 9A8D04xxxx | CALL xxxx:048D |
cs:00C7 | E95AFF | JMP 0024 ;//即 continue; 语句 |
其中ds:4b57 开始为《ascii码对应属性表》,具体内容为:
db 8 dup(20h) | ;00~07 |
db 20h,21h,21h | ;08~0A |
db 5 dup(20h) | ;0B~0F |
db 8 dup(20h) | ;10~17 |
db 8 dup(20h) | ;18~1F |
db 1,7 dup(0) | ;20~27 |
db 8 dup(0) | ;28~2F |
db 0Ah dup(2) | ;'0'~'9' |
db 6 dup(0) | ;3A~3F |
db 0,6 dup(14h) | ;'@',"ABCDEF" |
db 20 dup(4) | ;'G'~'Z' |
db 5 dup(0) | ;5B~5F |
db 0,6 dup(18h) | ;60,"abcdef" |
db 20 dup(8) | ;'g'~'z' |
db 4 dup(0) | ;7B~7E |
db 20h | ;7F |
db 80h dup(0) | ;80~FF |
汉化方法仍是将ascii80~FF的对应属性部分
(位于tcc.exe的第[29357h~293D6h]字节,原文为80h个字节,均为0),
换为80h dup(8h)。
以上所论皆是数据(data)。以下讨论代码(code),共须改动三处:
tcc 调用 fgetch(可能是 fgetch_1、fgetch_2、fgetch_3、fgetch_4)时:
原文 | 改作 | ||||
fgetch_4:file_offset == 0x10479 | |||||
cs:01F9 | 56 | push si | |||
do{lp_8=(lp_struct->lp8)++ | |||||
cs:01FA | C41E225F | les bx,[5F22] | |||
cs:01FE | 268B570E | mov dx,es:[bx+0E] | |||
cs:0202 | 268B470C | mov ax,es:[bx+0C] | |||
cs:0206 | 26FF470C | inc es:word ptr [bx+0C] | |||
cs:020A | 8BD8 | mov bx,ax | |||
cs:020C | 8EC2 | mov es,dx | |||
c=*lp8 | |||||
cs:020E | 268A07 | mov al,es:[bx] | cs:020E | 260FB607 | movzx ax,es:byte ptr [bx] |
cs:0211 | B400 | mov ah,00 | cs:0212 | 8BF0 | mov si,ax |
cs:0213 | 8BF0 | mov si,ax | cs:0214 | 3C80 | cmp al,80 |
cs:0216 | 0F82A500 | jb 02BF;//normal | |||
if(!(c & 0x80)) | |||||
cs:0215 | F7C68000 | test si,0080 | |||
cs:0219 | 7503 | jne 021E | cs:021A | 3CFF | cmp al,FF |
cs:021B | E9A100 | jmp 02BF;//normal | cs:021C | 740F | je 022D;//label_ff |
else if(c == 0xFE) | cs:021E | 3CFE | cmp al,FE | ||
cs:021E | 81FEFE00 | cmp si,00FE | cs:0220 | 0F84A800 | je 02CC;//nothing |
cs:0222 | 7503 | jne 0227 | |||
cs:0224 | E9A500 | jmp 02CC;//nothing | cs:0224 | 3C90 | cmp al,90 |
cs:0226 | 0F827E00 | jb 02A8;//label_8x | |||
else if(c == 0xFF) | cs:022A | EB1F | jmp 024B;//judge_fd | ||
cs:0227 | 81FEFF00 | cmp si,00FF | cs:022C | 90 | nop |
cs:022B | 751E | jne 024B;//judge_fd | |||
label_ff: | {lp_8=(lp_struct->lp8)++ | ||||
cs:022D | C41E225F | les bx,[5F22] | |||
cs:0231 | 268B570E | mov dx,es:[bx+0E] | |||
cs:0235 | 268B470C | mov ax,es:[bx+0C] | |||
cs:0239 | 26FF470C | inc es:word ptr [bx+0C] | |||
cs:023D | 8BD8 | mov bx,ax | |||
cs:023F | 8EC2 | mov es,dx | |||
c=*lp8 | |||||
cs:0241 | 268A07 | mov al,es:[bx] | |||
cs:0244 | B400 | mov ah,00 | |||
cs:0246 | 8BF0 | mov si,ax | |||
cs:0248 | EB79 | jmp 02C3 | |||
cs:024A | 90 | }nop | |||
judge_fd: | else if(c == 0xFD) | ||||
cs:024B | 81FEFD00 | cmp si,00FD | |||
cs:024F | 7557 | jne 02A8;//label_8x | cs:024F | 756E | jne 02BF;//normal |
{lp_8=(lp_struct->lp8)++ | |||||
cs:0251 | C41E225F | les bx,[5F22] | |||
cs:0255 | 268B570E | mov dx,es:[bx+0E] | |||
cs:0259 | 268B470C | mov ax,es:[bx+0C] | |||
cs:025D | 26FF470C | inc es:word ptr [bx+0C] | |||
cs:0261 | 8BD8 | mov bx,ax | |||
cs:0263 | 8EC2 | mov es,dx | |||
c=*lp8 | |||||
cs:0265 | 268A07 | mov al,es:[bx] | |||
cs:0268 | B400 | mov ah,00 | |||
cs:026A | 8BF0 | mov si,ax | |||
if((c&0x80==0)||(c>=0xFD)) | |||||
cs:026C | F7C68000 | test si,0080 | |||
cs:0270 | 7406 | je 0278 | |||
cs:0272 | 81FEFD00 | cmp si,00FD | |||
cs:0276 | 7C19 | jl 0291 | |||
cs:0278 | B81C00 | {mov ax,001C ;//enum of '# operator not followed by macro argument name' | |||
cs:027B | 50 | push ax | |||
cs:027C | 9AFB00F41E | call print_err;//xxxx.00FB | |||
cs:0281 | 44 | inc sp | |||
cs:0282 | 44 | inc sp | |||
... | |||||
cs:028F | EB3B | break;jmp 02CC | |||
} | |||||
cs:0291 | C41E225F | les bx,[5F22] | |||
cs:0295 | 26FF7706 | push es:word ptr [bx+06] | |||
cs:0299 | 26FF7704 | push es:word ptr [bx+04] | |||
cs:029D | 56 | push si | |||
cs:029E | 9A8205880C | call replace_macro;//cs:0582 | |||
cs:02A3 | B82200 | mov ax,0022 | |||
cs:02A6 | EB39 | }jmp 02E1 | |||
label_8x: | else{;//c=0x8? | ||||
cs:02A8 | C41E225F | les bx,[5F22] | |||
cs:02AC | 26FF7706 | push es:word ptr [bx+06] | |||
cs:02B0 | 26FF7704 | push es:word ptr [bx+04] | |||
cs:02B4 | 56 | push si | |||
cs:02B5 | 9A4E05880C | call reset_pointer;//cs:054E | |||
cs:02BA | E87A01 | call fgetch_2;//0437 | |||
cs:02BD | EB22 | }jmp 02E1 | |||
//if(!(c&80h)) | |||||
normal: | {if(c) | ||||
cs:02BF | 0BF6 | or si,si | |||
cs:02C1 | 7404 | je 02C7 | |||
cs:02C3 | 8BC6 EB1A | return(c); //mov ax,si; jmp 02E1 | |||
cs:02C7 | 9A8C03880C | else call free;//cs:038C | |||
} | |||||
nothing: | }while(lp_struct) | ||||
cs:02CC | A1225F | mov ax,[5F22] | |||
cs:02CF | 0B06245F | or ax,[5F24] | |||
cs:02D3 | 7403 | je 02D8 | |||
cs:02D5 | E922FF | jmp 01FA | |||
cs:02D8 | C7061C64C504 | mov word ptr [641C],04C5 | |||
cs:02DE | E8E401 | call fgetch_1;//04C5 | |||
cs:02E1 | 5E | pop si | |||
cs:02E2 | C3 | ret | |||
} | |||||
在处理汉字时,原文跳到label_8x(02a8) | 改动後跳到normal(02bf)。 |
原文 | 改作 | ||||
fgetch_2:file_offset == 0x106b7 | |||||
cs:0437 | C41E265F | les bx,[5F26] | |||
cs:043B | 26803F00 | cmp es:byte ptr [bx],00 | |||
cs:043F | 740A | je 044B | cs:043F | 7417 | je 0458 |
cs:0441 | FF06265F | inc word ptr [5F26] | cs:0441 | FF06265F | inc word ptr [5F26] |
cs:0445 | 268A07 | mov al,es:[bx] | cs:0445 | 260FB607 | movzx ax,es:byte ptr [bx] |
cs:0449 | 3C80 | cmp al,80 | |||
cs:044B | 720A | jb 0457 | |||
cs:044D | 3C90 | cmp al,90 | |||
cs:044F | 7204 | jb 0455 | |||
cs:0451 | 3CFD | cmp al,FD | |||
cs:0453 | 7202 | jb 0457 | |||
cs:0448 | 98 | cbw | cs:0455 | FECC | dec ah |
cs:0449 | EB29 | jmp 0474;return | cs:0457 | C3 | ret |
cs:044B | C706285F0000 | mov wo[5F28],0 | cs:0458 | 6633C0 | xor eax,eax |
cs:0451 | C706265F0000 | mov wo[5F26],0 | cs:045B | 66A3265F | mov [5F26],eax |
cs:0457 | A1225F | mov ax,[5F22] | cs:045F | 663306.. | xor eax,[5F22] |
cs:045A | 0B06245F | or ax,[5F24] | cs:0464 | BAC504 | mov dx,04C5;fgetch_1 |
cs:045E | 740B | je 046B | cs:0467 | 7403 | je 046C |
cs:0469 | BAF901 | mov dx,01F9;fgetch_4 | |||
cs:0460 | C7061C64F901 | {mov wo[641C],01F9 | cs:046C | 89161C64 | mov [641C],dx |
cs:0466 | E890FD | call fgetch_4;01F9 | cs:0470 | FFD2 | call dx |
cs:0469 | EB09 | }jmp 0474 | |||
cs:046B | C7061C64C504 | else{mov wo[641C],04C5 | |||
cs:0471 | E85100 | call fgetch_1;04C5 | |||
} | cs:0472 | C3 | ret | ||
cs:0473 | 90 | nop | |||
cs:0474 | C3 | ret | |||
} | |||||
在处理汉字时,原文在0448令AX为负数 | 改动後在0445令AX为正数。 |
原文 | 改作 | |||||
getch_in_macro(char c):file_offset == 0x11ef1 | ||||||
cs:0661 | 55 | push bp | ||||
cs:0662 | 8BEC | mov bp,sp | ||||
cs:0664 | F746 | if(c & 80h) | cs:0664 | 8A4606 | mov al,[bp+06] | |
068000 | test word ptr [bp+06],0080 | cs:0667 | 3C80 | cmp al,80 | ||
cs:0669 | 7436 | je 06A1;//nothing | cs:0669 | 7236 | jb 06A1;//nothing | |
{if(lp8<&(str[SIZE-1])) | cs:066B | 3C90 | cmp al,90 | |||
cs:066B | A13264 | mov ax,[6432] | cs:066D | 720A | jb 0679;//label_8x | |
cs:066E | 8CDA | mov dx,ds | cs:066F | 3CFC | cmp al,FC | |
cs:0670 | BB3474 | mov bx,7434 | cs:0671 | 762E | jbe 06A1;//nothing | |
cs:0673 | 8CD9 | mov cx,ds | cs:0673 | EB0F | jmp 0684;//judge_ov | |
cs:0675 | 3BC3 | cmp ax,bx | cs:0675 | 90 90 | nop | |
cs:0677 | 730B | jnb 0684;//judge_ov | cs:0677 | 90 90 | nop | |
label_8x: | {*(lp8++)=0xff | |||||
cs:0679 | 8BD8 | mov bx,ax | ||||
cs:067B | C607FF | mov byte ptr [bx],FF | ||||
cs:067E | FF063264 | inc word ptr [6432] | ||||
cs:0682 | EB1D | }jmp 06A1;//nothing | ||||
judge_ov: | else if(lp8==&(str[SIZE-1])) | |||||
cs:0684 | A13264 | mov ax,[6432] | ||||
cs:0687 | 8CDA | mov dx,ds | ||||
cs:0689 | BB3474 | mov bx,7434 | ||||
cs:068C | 8CD9 | mov cx,ds | ||||
cs:068E | 3BD1 | cmp dx,cx | cs:068E | 3BC3 | cmp ax,bx | |
cs:0690 | 750F | jne 06A1;//nothing | cs:0690 | 72E7 | jb 0679;//label_8x | |
cs:0692 | 3BC3 | cmp ax,bx | cs:0692 | 90 90 | nop | |
cs:0694 | 750B | jne 06A1;//nothing | ||||
cs:0696 | B82200 | {mov ax,0022 ;//enum of 'Macro expansion too long' | ||||
cs:0699 | 50 | push ax | ||||
cs:069A | 9AFB00F41E | call print_err;//xxxx.00FB | ||||
cs:069F | 8BE5 | mov sp,bp | ||||
} | ||||||
} | ||||||
cs:06A1 | nothing: | ... | ||||
cs:06D9 | 8BE5 | mov sp,bp | ||||
cs:06DB | 8B1E3264 | mov bx,[6432] | ||||
cs:06DF | C60700 | mov byte ptr [bx],00 | ||||
cs:06E2 | 5D | pop bp | ||||
cs:06E3 | CA0200 | retf 0002 | ||||
;} | ||||||
在处理汉字时,原文跳到 0679(label_8x) | 改动後跳到 06a1(nothing)。 |
至此,tcc.exe 1.0 版本汉化完毕。 函数名、变量名、宏名 均能用汉字。
但为便于日後tc编译链接,命名时请仍沿用下划线 或英文字母开头。
具体的asm,参阅https://sourceforge.net/projects/difc/files/turbo_c/1.0/
汉乃百族之长,唐为历朝之冠。当年中国在政治、军事、经济、文化等各方面均居世界前茅;
今日式微,我等後人不肖,编个程序连中文都不能用。
在此并非鼓吹连mov旨令、if关键字都得换成汉语,但若用1个中文变量也会引起编译错误,则起码可责其未考虑13亿人口的需求。
竹闲不自量力,推出TC汉化系列,冀可一振华夏之气。至于成败利钝,则非竹闲所能逆料也;
唯盼国人齐心戮力,重兴此尧唐的盛世,再睹我大汉的天威。
Turbo C 更高版本的汉化,敬请关注下期。(待续)
评论
发表评论