将Javascript代码转换为汇编
function print_str(astr)
{
let pstr = "劝君更尽一杯酒\n西出阳关无故人\n";
document.write(astr + pstr);
}
print_str("渭城朝雨浥轻尘\n客舍青青柳色新\n")
Javascript代码文件:just.js
编译:用 YC命令: ycc just.js 生成执行文件: just.exe
运行:在cmd界面执行just.exe后,输出下列文字:
渭城朝雨浥轻尘
客舍青青柳色新
劝君更尽一杯酒
西出阳关无故人
编译方式:
- 命令ycc just.js
只生成而不运行,只能检查语法错误,不能检查运行时错误。与YC编辑器的F6键功能《生成执行代码》相同。 - 命令ycc –c just.js
编译后自动运行,语法错误和运行时错误都可以检查出来,程序中用到的其它文件都被放入exe。若把程序拷贝到其它地方运行,只需要一个exe文件,而不必附带其它所用到的文件,与YC编辑器的F5键功能《生成js执行代码并检测错误》相同。
汇编代码:
把just.js调入YC编辑器,按Ctrl+F5键,生成下面的汇编代码。分析Javascript程序的汇编代码有助于理解Javascript的运行机理。
try_code //异常处理函数
{
016C4240 50 push eax //push try_pos
016C4241 ff7508 push dword [ebp+08h] //push pFunc
016C4244 ff75ac push dword [ebp-54h] //push stk_ptr
016C4247 57 push edi //push phtml
016C4248 e81f764902 call _int64 _stdcall js_try_proc(phtml,stk_ptr,pFunc,try_pos)
016C424D 8be2 mov esp,edx
016C424F 0bc0 or eax,eax //eax!=0时,eax为catch(…) 位置
016C4251 7503 jne (016C4256 = 016C4253+00000003)
016C4253 8b45a0 mov eax,dword [ebp-60h] //eax=程序结束位置
016C4256 ffe0 jmp eax //跳到catch(…)或程序结束位置
}
//全局代码
0 var this //变量this
1 var print_str funcNo=1 argnum=1 obj_10000111 //变量print_str
2 var document //变量document
{
08C20790 55 push ebp
08C20791 8bec mov ebp,esp
08C20793 83ec60 sub esp,0x00000060
08C20796 53 push ebx
08C20797 56 push esi
08C20798 57 push edi
08C20799 8b5d08 mov ebx,dword [ebp+08h] //ebx = FUNC_STRUCTDATA *pFunc
08C2079C ff7344 push dword [ebx+44h] //push pFunc->arg_ebp
08C2079F 896b44 mov dword [ebx+44h],ebp //pFunc->arg_ebp = ebp
08C207A2 bfc87da404 mov edi,0x04A47DC8 //edi = phtml
08C207A7 8b37 mov esi,dword [edi] //esi = jdt->func_stack_Mem.locvarBuf
08C207A9 8965ac mov dword [ebp-54h],esp //try_stack = esp
08C207AC c745a05908c208 mov dword [ebp-60h],0x08C20859 //try_exitPos = 08C20859
08C207B3 8d8424e0ef0a00 lea eax,[esp+AEFE0h]
08C207BA 3b8700030000 cmp eax,dword [edi+300h] //比较esp+AEFF0h 和s tack_top
08C207C0 770b ja (08C207CD = 08C207C2+0000000b) //判断堆栈是否溢出
08C207C2 57 push edi
08C207C3 e80bb4f3fa call int _stdcall memory_overflow(YHTML *jdt)//堆栈溢出处理
08C207C8 e9733aaaf8 jmp (016C4240 = 8C207CD+f8aa3a73) //退出程序
08C207CD 83ec20 sub esp,0x00000020
08C207D0 66c704240608 mov word [esp],0x0806 //设置[esp] = "渭城朝雨浥轻尘..."
08C207D6 c74424080889a408 mov dword [esp+08h],0x08A48908
08C207DE c744240c10000000 mov dword [esp+0Ch],0x00000010
08C207E6 54 push esp //push argval
08C207E7 6a01 push 0x00000001 //push argnum = 1
08C207E9 8d442418 lea eax,[esp+18h]
08C207ED 50 push eax //push pReturnV
08C207EE 807e1007 cmp byte [esi+10h],0x07 //判断变量是否是对象
08C207F2 740c je (08C20800 = 08C207F4+0000000c)
08C207F4 8d5610 lea edx,[esi+10h]
08C207F7 52 push edx //push srcdat 嵌入到Javascript的C/C++函数之地址
08C207F8 57 push edi //push phtml
08C207F9 e88abbf7fa call void js_call_cpp_function(jdt,...) //调用c/c++函数
08C207FE eb42 jmp (08C20842 = 8C20800+0000042)
08C20800 8b7e1c mov edi,dword [esi+1Ch] //以下代码取出变量, 如:print_str
08C20803 ba806967ff mov edx,0xFF676980
08C20808 2b5618 sub edx,dword [esi+18h]
08C2080B 8b4738 mov eax,dword [edi+38h]
08C2080E 8b0490 mov eax,dword [eax+edx*4]
08C20811 8b00 mov eax,dword [eax]
08C20813 8b4824 mov ecx,dword [eax+24h] //[ecx] = print_str
08C20816 80790c11 cmp byte [ecx+0Ch],0x11 //判断变量是否是JS函数
08C2081A 75d8 jne (08C207F4 = 08C2081C+ffffffd8)
08C2081C 8b4010 mov eax,dword [eax+10h]
08C2081F 83f800 cmp eax,0x00000000 //判断是否是JS内置函数
08C20822 7f0d jg (08C20831 = 08C20824+0000000d)
08C20824 6a00 push 0x00000000 //push objdat 以下执行JS内置函数
08C20826 50 push eax //push funcNo
08C20827 6a00 push 0x00000000 //push new_flag
08C20829 57 push edi //push phtml
08C2082A e800baf7fa call void _stdcall js_call_inner_function(YHTML *jdt,...)
08C2082F eb11 jmp (08C20842 = 8C20831+0000011)
08C20831 6a00 push 0x00000000
08C20833 6a00 push 0x00000000
08C20835 8b9714020000 mov edx,dword [edi+214h]
08C2083B 8b0482 mov eax,dword [edx+eax*4]
08C2083E 50 push eax
08C2083F ff5008 call dword [eax+08h] //调用 print_str() 函数
08C20842 83c410 add esp,0x00000010
08C20845 66833c2406 cmp word [esp],0x0006 //判断函数返回值是否需释放内存
08C2084A 750a jne (08C20856 = 08C2084C+0000000a)
08C2084C ff742408 push dword [esp+08h]
08C20850 e8dfb3f3fa call void free(void *_Memory) //释放字符串所占内存
08C20855 59 pop ecx
08C20856 83c410 add esp,0x00000010
08C20859 8b5d08 mov ebx,dword [ebp+08h] //ebx = pFunc
08C2085C 8f4344 pop dword [ebx+44h] //pop pFunc->arg_ebp
08C2085F 5f pop edi
08C20860 5e pop esi
08C20861 5b pop ebx
08C20862 8be5 mov esp,ebp
08C20864 5d pop ebp
08C20865 c21800 ret 0018
}
----------------函数 print_str(astr) func=1 parentFunc=0 argnum=1
0 var astr //形式变量
1 const this //this对象
2 const arguments //arguments 对象
3 let pstr //局部变量
{
08BB29A8 55 push ebp
08BB29A9 8bec mov ebp,esp
08BB29AB 81eca0000000 sub esp,0x000000A0
08BB29B1 53 push ebx
08BB29B2 56 push esi
08BB29B3 57 push edi
08BB29B4 8b5d08 mov ebx,dword [ebp+08h] //ebx = pFunc
08BB29B7 ff7344 push dword [ebx+44h] //push pFunc->arg_ebp
08BB29BA 896b44 mov dword [ebx+44h],ebp //pFunc->arg_ebp = ebp
08BB29BD 8b4304 mov eax,dword [ebx+04h]
08BB29C0 83f808 cmp eax,0x00000008
08BB29C3 7506 jne (08BB29CB = 08BB29C5+00000006)
08BB29C5 53 push ebx //申请局部堆栈指针缓冲区
08BB29C6 e8ab90fafa call int _stdcall alloc_function_locmem(FUNC_STRUCTDATA *pFunc)
08BB29CB 8d9560ffffff lea edx,[ebp-A0h]
08BB29D1 8b0b mov ecx,dword [ebx]
08BB29D3 891481 mov dword [ecx+eax*4],edx //设置局部堆栈地址
08BB29D6 ff4304 inc dword [ebx+04h] //局部堆栈号 += 1
08BB29D9 b001 mov al,0x01 //al = undefined
08BB29DB 8b4d14 mov ecx,dword [ebp+14h] //ecx = 函数返回值地址
08BB29DE 8801 mov byte [ecx],al //设置函数返回值 = undefined
08BB29E0 888560ffffff mov byte [ebp-A0h],al //设置 astr = undefined
08BB29E6 888570ffffff mov byte [ebp-90h],al //设置 this = undefined
08BB29EC 884580 mov byte [ebp-80h],al //设置 arguments = undefined
08BB29EF 884590 mov byte [ebp-70h],al //设置 pstr = undefined
08BB29F2 8b4d18 mov ecx,dword [ebp+18h]
08BB29F5 83f901 cmp ecx,0x00000001
08BB29F8 7605 jbe (08BB29FF = 08BB29FA+00000005)
08BB29FA b901000000 mov ecx,0x00000001
08BB29FF c1e102 shl ecx,0x02
08BB2A02 8b751c mov esi,dword [ebp+1Ch]
08BB2A05 8dbd60ffffff lea edi,[ebp-A0h]
08BB2A0B f3a5 repe movsd
08BB2A0D bfc87da404 mov edi,0x04A47DC8
08BB2A12 8b472c mov eax,dword [edi+2Ch] //eax = pFunction
08BB2A15 8945a8 mov dword [ebp-58h],eax
08BB2A18 ff772c push dword [edi+2Ch] //push pFunction
08BB2A1B ff7508 push dword [ebp+08h] //push pFunc
08BB2A1E 8f472c pop dword [edi+2Ch] //pop pFunction
08BB2A21 8b37 mov esi,dword [edi]
08BB2A23 8965ac mov dword [ebp-54h],esp
08BB2A26 c745a0ef2abb08 mov dword [ebp-60h],0x08BB2AEF
08BB2A2D 837f2800 cmp dword [edi+28h],0x00000000
08BB2A31 7407 je (08BB2A3A = 08BB2A33+00000007)
08BB2A33 33c0 xor eax,eax
08BB2A35 e90618b1f8 jmp (016C4240 = 8BB2A3A+f8b11806)
08BB2A3A 66c745900608 mov word [ebp-70h],0x0806 //设置pstr的类型为JS_string_const
08BB2A40 c74598e088a408 mov dword [ebp-68h],0x08A488E0 //设置pstr = "劝君更尽一杯酒..."
08BB2A47 c7459c0f000000 mov dword [ebp-64h],0x0000000F //设置pstr.length = 15
08BB2A4E 8d8424e0ef0a00 lea eax,[esp+AEFE0h]
08BB2A55 3b8700030000 cmp eax,dword [edi+300h] //比较esp+AEFF0h 和s tack_top
08BB2A5B 770b ja (08BB2A68 = 08BB2A5D+0000000b) //判断堆栈是否溢出
08BB2A5D 57 push edi
08BB2A5E e87091fafa call int _stdcall memory_overflow(YHTML *jdt) //堆栈溢出处理
08BB2A63 e9d817b1f8 jmp (016C4240 = 8BB2A68+f8b117d8) //退出程序
08BB2A68 83ec20 sub esp,0x00000020
08BB2A6B 83ec10 sub esp,0x00000010
08BB2A6E 8d5590 lea edx,[ebp-70h]
08BB2A71 52 push edx //push pstr
08BB2A72 8d9560ffffff lea edx,[ebp-A0h] //edx = astr 的地址
08BB2A78 52 push edx //push astr
08BB2A79 8d442408 lea eax,[esp+08h] //eax = stk_ptr
08BB2A7D 50 push eax //push stk_ptr
08BB2A7E e88ba4fefa call void _stdcall js_val_add_val_to_stack(JSVAL *stk_ptr,...)
08BB2A83 83c410 add esp,0x00000010
08BB2A86 8b4424f0 mov eax,dword [esp-10h] //esp-10h = astr + pstr 的地址
08BB2A8A 663d0601 cmp ax,0106
08BB2A8E 7507 jne (08BB2A97 = 08BB2A90+00000007)
08BB2A90 0d00020000 or eax,0x00000200
08BB2A95 eb05 jmp (08BB2A9C = 8BB2A97+0000005)
08BB2A97 0d00010000 or eax,0x00000100
08BB2A9C 890424 mov dword [esp],eax
08BB2A9F 8b4424f8 mov eax,dword [esp-08h]
08BB2AA3 89442408 mov dword [esp+08h],eax
08BB2AA7 8b4424fc mov eax,dword [esp-04h]
08BB2AAB 8944240c mov dword [esp+0Ch],eax
08BB2AAF 54 push esp //push argval = astr + pstr
08BB2AB0 6a01 push 0x00000001 //push argnum = 1
08BB2AB2 8d55c0 lea edx,[ebp-40h]
08BB2AB5 52 push edx //push desJval
08BB2AB6 6a02 push 0x00000002 //push LOCAL_pos
08BB2AB8 68f2000001 push 0x010000F2 //push vName = 010000F2
08BB2ABD 6899990000 push 0x00009999 //push var_deep
08BB2AC2 57 push edi //push phtml
08BB2AC3 e86e94fefa call JSVAL* _stdcall js_get_parent_var(YHTML *jdt,...)
08BB2AC8 8bd8 mov ebx,eax //eax = objdat
08BB2ACA 53 push ebx //push objdat
08BB2ACB 6a00 push 0x00000000 //push new_flag = 0
08BB2ACD 68f2030001 push 0x010003F2 //push vName = 010003F2
08BB2AD2 57 push edi //push phtml call document.write()
08BB2AD3 e8cf7efefa call void _stdcall js_call_object_method(YHTML *jdt,...)
08BB2AD8 83c410 add esp,0x00000010
08BB2ADB 66833c2406 cmp word [esp],0x0006 //[esp] = document.write() 的返回值
08BB2AE0 750a jne (08BB2AEC = 08BB2AE2+0000000a)
08BB2AE2 ff742408 push dword [esp+08h]
08BB2AE6 e84991fafa call void free(void *_Memory) //释放字符串所占内存
08BB2AEB 59 pop ecx
08BB2AEC 83c410 add esp,0x00000010
08BB2AEF 8b5d08 mov ebx,dword [ebp+08h] //ebx = pFunc
08BB2AF2 807b4b00 cmp byte [ebx+4Bh],0x00
08BB2AF6 7406 je (08BB2AFE = 08BB2AF8+00000006)
08BB2AF8 57 push edi
08BB2AF9 e8bb8bfafa call void _stdcall save_parent_local_var(YHTML *jdt)
08BB2AFE b904000000 mov ecx,0x00000004
08BB2B03 8db560ffffff lea esi,[ebp-A0h]
08BB2B09 66813e0604 cmp word [esi],0x0406 //以下循环释放局部变量字符串所占内存
08BB2B0E 750b jne (08BB2B1B = 08BB2B10+0000000b)
08BB2B10 51 push ecx
08BB2B11 ff7608 push dword [esi+08h]
08BB2B14 e81b91fafa call void free(void *_Memory) //释放字符串所占内存
08BB2B19 59 pop ecx
08BB2B1A 59 pop ecx
08BB2B1B 83c610 add esi,0x00000010
08BB2B1E e2e9 loop (08BB2B09 = 08BB2B20+ffffffe9)
08BB2B20 8b4d18 mov ecx,dword [ebp+18h]
08BB2B23 e31e jecxz (08BB2B43 = 08BB2B25+0000001e)
08BB2B25 8b751c mov esi,dword [ebp+1Ch]
08BB2B28 803e06 cmp byte [esi],0x06
08BB2B2B 7511 jne (08BB2B3E = 08BB2B2D+00000011)
08BB2B2D 807e0101 cmp byte [esi+01h],0x01 //以下循环释放形式变量字符串所占内存
08BB2B31 770b ja (08BB2B3E = 08BB2B33+0000000b)
08BB2B33 51 push ecx
08BB2B34 ff7608 push dword [esi+08h]
08BB2B37 e8f890fafa call void free(void *_Memory) //释放字符串所占内存
08BB2B3C 59 pop ecx
08BB2B3D 59 pop ecx
08BB2B3E 83c610 add esi,0x00000010
08BB2B41 e2e5 loop (08BB2B28 = 08BB2B43+ffffffe5)
08BB2B43 837b0c00 cmp dword [ebx+0Ch],0x00000000 //判断本函数是否调用了eval()函数
08BB2B47 7406 je (08BB2B4F = 08BB2B49+00000006)
08BB2B49 57 push edi //以下释放 eval() 语句所申请的内存
08BB2B4A e8818ffafa call void _stdcall eval_var_free(YHTML *jdt)
08BB2B4F 807d1000 cmp byte [ebp+10h],0x00 //判断是否用 new 调用了该函数
08BB2B53 740f je (08BB2B64 = 08BB2B55+0000000f)
08BB2B55 8b4514 mov eax,dword [ebp+14h] //eax = 返回值地址
08BB2B58 803807 cmp byte [eax],0x07 //判断返回值是否是对象
08BB2B5B 7407 je (08BB2B64 = 08BB2B5D+00000007)
08BB2B5D 50 push eax //eax = 返回值地址
08BB2B5E 57 push edi //如果返回值不是对象, 则调用下面函数创建new所需对象
08BB2B5F e8de8dfafa call void _stdcall create_this_object(YHTML *jdt,JSVAL *pJval)
08BB2B64 8f472c pop dword [edi+2Ch] //pop pFunction
08BB2B67 ff4b04 dec dword [ebx+04h] //局部堆栈号 -= 1
08BB2B6A 8f4344 pop dword [ebx+44h] //pop pFunc->arg_ebp
08BB2B6D 5f pop edi
08BB2B6E 5e pop esi
08BB2B6F 5b pop ebx
08BB2B70 8be5 mov esp,ebp
08BB2B72 5d pop ebp
08BB2B73 c21800 ret 0018
}
注:生成Javascript汇编代码主要由文件ycjit.cpp完成,还有许多优化空间待将来实现。64位版本Javascript转汇编正在测试中。
转载:https://blog.csdn.net/xiaobingyang/article/details/104985387
查看评论