Archive for the ‘assembler’ Category

  1. Hello, COM(GAS) World!

    Posted on 3月 18th, 2013 by cx20

    COM(GAS)

    COM(Component Object Model)はマイクロソフトの提唱するプログラム部品の仕様である。
    COM を用いて開発された部品であれば言語を問わず利用することができる。
    以下は GAS による COM クライアントの例となっている。

    ソースコード

            .file   "hello.c"
            .def    ___main;        .scl    2;      .type   32;     .endef
            .section .rdata,"dr"
            .align 4
    LC0:
            .ascii "B

    上記コードは以下のC言語のソースを GCC でアセンブリコード出力(gcc -s hello.c)したものに相当する。

    #include <ole2.h>
     
    int main( int argc, char* argv[] )
    {
        CLSID clsid;
        IDispatch* pShell;
        IDispatch* pFolder;
        DISPID dispid;
        OLECHAR* ptName = L"BrowseForFolder";
        DISPPARAMS param = { NULL, NULL, 0, 0 };
        VARIANT varg[4];
        VARIANT vResult;
     
        CoInitialize( NULL );
     
        CLSIDFromProgID(L"Shell.Application", &clsid );
        CoCreateInstance( &clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IDispatch, (void**)&pShell);
        pShell->lpVtbl->GetIDsOfNames( (void*)pShell, &IID_NULL, &ptName, 1, GetUserDefaultLCID(), &dispid );
     
        VariantInit( &varg[0] );
        varg[0].vt = VT_I4;
        varg[0].lVal = 36L;  /* ssfWINDOWS */
     
        VariantInit( &varg[1] );
        varg[1].vt = VT_I4;
        varg[1].lVal = 0L;
     
        VariantInit( &varg[2] );
        varg[2].vt = VT_BSTR;
        varg[2].bstrVal = SysAllocString(L"Hello, COM World!"); 
     
        VariantInit( &varg[3] );
        varg[3].vt = VT_I4;
        varg[3].lVal = 0L;
     
        param.cArgs = 4;
        param.rgvarg = varg;
     
        pShell->lpVtbl->Invoke( (void*)pShell, dispid, &IID_NULL, GetUserDefaultLCID(), DISPATCH_METHOD, &param, &vResult, NULL, NULL );
     
        VariantInit( &varg[0] );
        VariantInit( &varg[1] );
        VariantInit( &varg[2] );
        VariantInit( &varg[3] );
     
        pFolder = V_DISPATCH( &vResult );
        if ( pFolder != NULL )
        {
            pFolder->lpVtbl->Release( (void*)pFolder );
        }
        pShell->lpVtbl->Release( (void*)pShell );
     
        CoUninitialize();
     
        return 0;
    }

    コンパイル&リンク方法

    C:¥> gcc -c hello.c
    C:¥> gcc -o hello hello.o -l ole32  -l oleaut32 -l uuid

    実行結果

    +----------------------------------------+
    |Browse For Folder                    [X]|
    +----------------------------------------+
    | Hello, COM Wolrd!                      |
    |                                        |
    | +------------------------------------+ |
    | |[Windows]                           | |
    | | +[addins]                          | |
    | | +[AppCompat]                       | |
    | | +[AppPatch]                        | |
    | | +[assembly]                        | |
    | |     :                              | |
    | |     :                              | |
    | |     :                              | |
    | +------------------------------------+ |
    | [Make New Folder]    [  OK  ] [Cancel] |
    +----------------------------------------+
  2. Hello, COM(LLVM) World!

    Posted on 3月 17th, 2013 by cx20

    COM(LLVM)

    COM(Component Object Model)はマイクロソフトの提唱するプログラム部品の仕様である。
    COM を用いて開発された部品であれば言語を問わず利用することができる。
    以下は LLVM Assembler による COM クライアントの例となっている。

    ソースコード

    ; ModuleID = 'hello.c'
    target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-f80:128:128-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32-S32"
    target triple = "i686-w64-mingw32"
     
    %struct._GUID = type { i32, i16, i16, [8 x i8] }
    %struct.IDispatch = type { %struct.IDispatchVtbl* }
    %struct.IDispatchVtbl = type { i32 (%struct.IDispatch*, %struct._GUID*, i8**)*, i32 (%struct.IDispatch*)*, i32 (%struct.IDispatch*)*, i32 (%struct.IDispatch*, i32*)*, i32 (%struct.IDispatch*, i32, i32, %struct.ITypeInfo**)*, i32 (%struct.IDispatch*, %struct._GUID*, i16**, i32, i32, i32*)*, i32 (%struct.IDispatch*, i32, %struct._GUID*, i32, i16, %struct.tagDISPPARAMS*, %struct.tagVARIANT*, %struct.tagEXCEPINFO*, i32*)* }
    %struct.ITypeInfo = type { %struct.ITypeInfoVtbl* }
    %struct.ITypeInfoVtbl = type { i32 (%struct.ITypeInfo*, %struct._GUID*, i8**)*, i32 (%struct.ITypeInfo*)*, i32 (%struct.ITypeInfo*)*, i32 (%struct.ITypeInfo*, %struct.tagTYPEATTR**)*, i32 (%struct.ITypeInfo*, %struct.ITypeComp**)*, i32 (%struct.ITypeInfo*, i32, %struct.tagFUNCDESC**)*, i32 (%struct.ITypeInfo*, i32, %struct.tagVARDESC**)*, i32 (%struct.ITypeInfo*, i32, i16**, i32, i32*)*, i32 (%struct.ITypeInfo*, i32, i32*)*, i32 (%struct.ITypeInfo*, i32, i32*)*, i32 (%struct.ITypeInfo*, i16**, i32, i32*)*, i32 (%struct.ITypeInfo*, i8*, i32, i16, %struct.tagDISPPARAMS*, %struct.tagVARIANT*, %struct.tagEXCEPINFO*, i32*)*, i32 (%struct.ITypeInfo*, i32, i16**, i16**, i32*, i16**)*, i32 (%struct.ITypeInfo*, i32, i32, i16**, i16**, i16*)*, i32 (%struct.ITypeInfo*, i32, %struct.ITypeInfo**)*, i32 (%struct.ITypeInfo*, i32, i32, i8**)*, i32 (%struct.ITypeInfo*, %struct.IUnknown*, %struct._GUID*, i8**)*, i32 (%struct.ITypeInfo*, i32, i16**)*, i32 (%struct.ITypeInfo*, %struct.ITypeLib**, i32*)*, void (%struct.ITypeInfo*, %struct.tagTYPEATTR*)*, void (%struct.ITypeInfo*, %struct.tagFUNCDESC*)*, void (%struct.ITypeInfo*, %struct.tagVARDESC*)* }
    %struct.tagTYPEATTR = type <{ %struct._GUID, i32, i32, i32, i32, i16*, i32, i32, i16, i16, i16, i16, i16, i16, i16, i16, %struct.tagTYPEDESC, %struct.tagIDLDESC }>
    %struct.tagTYPEDESC = type <{ %union.anon, i16, [2 x i8] }>
    %union.anon = type { %struct.tagTYPEDESC* }
    %struct.tagIDLDESC = type { i32, i16 }
    %struct.ITypeComp = type { %struct.ITypeCompVtbl* }
    %struct.ITypeCompVtbl = type { i32 (%struct.ITypeComp*, %struct._GUID*, i8**)*, i32 (%struct.ITypeComp*)*, i32 (%struct.ITypeComp*)*, i32 (%struct.ITypeComp*, i16*, i32, i16, %struct.ITypeInfo**, i32*, %union.tagBINDPTR*)*, i32 (%struct.ITypeComp*, i16*, i32, %struct.ITypeInfo**, %struct.ITypeComp**)* }
    %union.tagBINDPTR = type { %struct.tagFUNCDESC* }
    %struct.tagFUNCDESC = type <{ i32, i32*, %struct.tagELEMDESC*, i32, i32, i32, i16, i16, i16, i16, %struct.tagELEMDESC, i16, [2 x i8] }>
    %struct.tagELEMDESC = type <{ %struct.tagTYPEDESC, %union.anon.0 }>
    %union.anon.0 = type { %struct.tagIDLDESC }
    %struct.tagVARDESC = type <{ i32, i16*, %union.anon.9, %struct.tagELEMDESC, i16, [2 x i8], i32 }>
    %union.anon.9 = type { i32 }
    %struct.tagDISPPARAMS = type { %struct.tagVARIANT*, i32*, i32, i32 }
    %struct.tagVARIANT = type { %union.anon.1 }
    %union.anon.1 = type { %struct.anon }
    %struct.anon = type { i16, i16, i16, i16, %union.anon.2 }
    %union.anon.2 = type { i64 }
    %struct.tagEXCEPINFO = type { i16, i16, i16*, i16*, i16*, i32, i8*, i32 (%struct.tagEXCEPINFO*)*, i32 }
    %struct.IUnknown = type { %struct.IUnknownVtbl* }
    %struct.IUnknownVtbl = type { i32 (%struct.IUnknown*, %struct._GUID*, i8**)*, i32 (%struct.IUnknown*)*, i32 (%struct.IUnknown*)* }
    %struct.ITypeLib = type { %struct.ITypeLibVtbl* }
    %struct.ITypeLibVtbl = type { i32 (%struct.ITypeLib*, %struct._GUID*, i8**)*, i32 (%struct.ITypeLib*)*, i32 (%struct.ITypeLib*)*, i32 (%struct.ITypeLib*)*, i32 (%struct.ITypeLib*, i32, %struct.ITypeInfo**)*, i32 (%struct.ITypeLib*, i32, i32*)*, i32 (%struct.ITypeLib*, %struct._GUID*, %struct.ITypeInfo**)*, i32 (%struct.ITypeLib*, %struct.tagTLIBATTR**)*, i32 (%struct.ITypeLib*, %struct.ITypeComp**)*, i32 (%struct.ITypeLib*, i32, i16**, i16**, i32*, i16**)*, i32 (%struct.ITypeLib*, i16*, i32, i32*)*, i32 (%struct.ITypeLib*, i16*, i32, %struct.ITypeInfo**, i32*, i16*)*, void (%struct.ITypeLib*, %struct.tagTLIBATTR*)* }
    %struct.tagTLIBATTR = type <{ %struct._GUID, i32, i32, i16, i16, i16, [2 x i8] }>
     
    @.str = private unnamed_addr constant [16 x i16] [i16 66, i16 114, i16 111, i16 119, i16 115, i16 101, i16 70, i16 111, i16 114, i16 70, i16 111, i16 108, i16 100, i16 101, i16 114, i16 0], align 2
    @.str1 = private unnamed_addr constant [18 x i16] [i16 83, i16 104, i16 101, i16 108, i16 108, i16 46, i16 65, i16 112, i16 112, i16 108, i16 105, i16 99, i16 97, i16 116, i16 105, i16 111, i16 110, i16 0], align 2
    @IID_IDispatch = external constant %struct._GUID
    @GUID_NULL = external constant %struct._GUID
    @.str2 = private unnamed_addr constant [18 x i16] [i16 72, i16 101, i16 108, i16 108, i16 111, i16 44, i16 32, i16 67, i16 79, i16 77, i16 32, i16 87, i16 111, i16 114, i16 108, i16 100, i16 33, i16 0], align 2
     
    define i32 @main(i32 %argc, i8** nocapture %argv) nounwind {
      %clsid = alloca %struct._GUID, align 4
      %pShell = alloca %struct.IDispatch*, align 4
      %dispid = alloca i32, align 4
      %ptName = alloca i16*, align 4
      %param = alloca %struct.tagDISPPARAMS, align 4
      %varg = alloca [4 x %struct.tagVARIANT], align 8
      %vResult = alloca %struct.tagVARIANT, align 8
      store i16* getelementptr inbounds ([16 x i16]* @.str, i32 0, i32 0), i16** %ptName, align 4, !tbaa !0
      %1 = bitcast %struct.tagDISPPARAMS* %param to i8*
      call void @llvm.memset.p0i8.i32(i8* %1, i8 0, i32 16, i32 4, i1 false)
      %2 = call x86_stdcallcc i32 @CoInitialize(i8* null) nounwind
      %3 = call x86_stdcallcc i32 @CLSIDFromProgID(i16* getelementptr inbounds ([18 x i16]* @.str1, i32 0, i32 0), %struct._GUID* %clsid) nounwind
      %4 = bitcast %struct.IDispatch** %pShell to i8**
      %5 = call x86_stdcallcc i32 @CoCreateInstance(%struct._GUID* %clsid, %struct.IUnknown* null, i32 1, %struct._GUID* @IID_IDispatch, i8** %4) nounwind
      %6 = load %struct.IDispatch** %pShell, align 4, !tbaa !0
      %7 = getelementptr inbounds %struct.IDispatch* %6, i32 0, i32 0
      %8 = load %struct.IDispatchVtbl** %7, align 4, !tbaa !0
      %9 = getelementptr inbounds %struct.IDispatchVtbl* %8, i32 0, i32 5
      %10 = load i32 (%struct.IDispatch*, %struct._GUID*, i16**, i32, i32, i32*)** %9, align 4, !tbaa !0
      %11 = call x86_stdcallcc i32 @GetUserDefaultLCID() nounwind
      %12 = call x86_stdcallcc i32 %10(%struct.IDispatch* %6, %struct._GUID* @GUID_NULL, i16** %ptName, i32 1, i32 %11, i32* %dispid) nounwind
      %13 = getelementptr inbounds [4 x %struct.tagVARIANT]* %varg, i32 0, i32 0
      call x86_stdcallcc void @VariantInit(%struct.tagVARIANT* %13) nounwind
      %14 = getelementptr inbounds [4 x %struct.tagVARIANT]* %varg, i32 0, i32 0, i32 0, i32 0, i32 0
      store i16 3, i16* %14, align 8, !tbaa !3
      %15 = getelementptr inbounds [4 x %struct.tagVARIANT]* %varg, i32 0, i32 0, i32 0, i32 0, i32 4
      %16 = bitcast %union.anon.2* %15 to i32*
      store i32 36, i32* %16, align 8, !tbaa !4
      %17 = getelementptr inbounds [4 x %struct.tagVARIANT]* %varg, i32 0, i32 1
      call x86_stdcallcc void @VariantInit(%struct.tagVARIANT* %17) nounwind
      %18 = getelementptr inbounds %struct.tagVARIANT* %17, i32 0, i32 0, i32 0, i32 0
      store i16 3, i16* %18, align 8, !tbaa !3
      %19 = getelementptr inbounds [4 x %struct.tagVARIANT]* %varg, i32 0, i32 1, i32 0, i32 0, i32 4
      %20 = bitcast %union.anon.2* %19 to i32*
      store i32 0, i32* %20, align 8, !tbaa !4
      %21 = getelementptr inbounds [4 x %struct.tagVARIANT]* %varg, i32 0, i32 2
      call x86_stdcallcc void @VariantInit(%struct.tagVARIANT* %21) nounwind
      %22 = getelementptr inbounds %struct.tagVARIANT* %21, i32 0, i32 0, i32 0, i32 0
      store i16 8, i16* %22, align 8, !tbaa !3
      %23 = call x86_stdcallcc i16* @SysAllocString(i16* getelementptr inbounds ([18 x i16]* @.str2, i32 0, i32 0)) nounwind
      %24 = getelementptr inbounds [4 x %struct.tagVARIANT]* %varg, i32 0, i32 2, i32 0, i32 0, i32 4
      %25 = bitcast %union.anon.2* %24 to i16**
      store i16* %23, i16** %25, align 8, !tbaa !0
      %26 = getelementptr inbounds [4 x %struct.tagVARIANT]* %varg, i32 0, i32 3
      call x86_stdcallcc void @VariantInit(%struct.tagVARIANT* %26) nounwind
      %27 = getelementptr inbounds %struct.tagVARIANT* %26, i32 0, i32 0, i32 0, i32 0
      store i16 3, i16* %27, align 8, !tbaa !3
      %28 = getelementptr inbounds [4 x %struct.tagVARIANT]* %varg, i32 0, i32 3, i32 0, i32 0, i32 4
      %29 = bitcast %union.anon.2* %28 to i32*
      store i32 0, i32* %29, align 8, !tbaa !4
      %30 = getelementptr inbounds %struct.tagDISPPARAMS* %param, i32 0, i32 2
      store i32 4, i32* %30, align 4, !tbaa !5
      %31 = getelementptr inbounds %struct.tagDISPPARAMS* %param, i32 0, i32 0
      store %struct.tagVARIANT* %13, %struct.tagVARIANT** %31, align 4, !tbaa !0
      %32 = load %struct.IDispatch** %pShell, align 4, !tbaa !0
      %33 = getelementptr inbounds %struct.IDispatch* %32, i32 0, i32 0
      %34 = load %struct.IDispatchVtbl** %33, align 4, !tbaa !0
      %35 = getelementptr inbounds %struct.IDispatchVtbl* %34, i32 0, i32 6
      %36 = load i32 (%struct.IDispatch*, i32, %struct._GUID*, i32, i16, %struct.tagDISPPARAMS*, %struct.tagVARIANT*, %struct.tagEXCEPINFO*, i32*)** %35, align 4, !tbaa !0
      %37 = load i32* %dispid, align 4, !tbaa !4
      %38 = call x86_stdcallcc i32 @GetUserDefaultLCID() nounwind
      %39 = call x86_stdcallcc i32 %36(%struct.IDispatch* %32, i32 %37, %struct._GUID* @GUID_NULL, i32 %38, i16 zeroext 1, %struct.tagDISPPARAMS* %param, %struct.tagVARIANT* %vResult, %struct.tagEXCEPINFO* null, i32* null) nounwind
      call x86_stdcallcc void @VariantInit(%struct.tagVARIANT* %13) nounwind
      call x86_stdcallcc void @VariantInit(%struct.tagVARIANT* %17) nounwind
      call x86_stdcallcc void @VariantInit(%struct.tagVARIANT* %21) nounwind
      call x86_stdcallcc void @VariantInit(%struct.tagVARIANT* %26) nounwind
      %40 = getelementptr inbounds %struct.tagVARIANT* %vResult, i32 0, i32 0, i32 0, i32 4
      %41 = bitcast %union.anon.2* %40 to %struct.IDispatch**
      %42 = load %struct.IDispatch** %41, align 8, !tbaa !0
      %43 = icmp eq %struct.IDispatch* %42, null
      br i1 %43, label %50, label %44
     
    ; <label>:44                                      ; preds = %0
      %45 = getelementptr inbounds %struct.IDispatch* %42, i32 0, i32 0
      %46 = load %struct.IDispatchVtbl** %45, align 4, !tbaa !0
      %47 = getelementptr inbounds %struct.IDispatchVtbl* %46, i32 0, i32 2
      %48 = load i32 (%struct.IDispatch*)** %47, align 4, !tbaa !0
      %49 = call x86_stdcallcc i32 %48(%struct.IDispatch* %42) nounwind
      br label %50
     
    ; <label>:50                                      ; preds = %0, %44
      %51 = load %struct.IDispatch** %pShell, align 4, !tbaa !0
      %52 = getelementptr inbounds %struct.IDispatch* %51, i32 0, i32 0
      %53 = load %struct.IDispatchVtbl** %52, align 4, !tbaa !0
      %54 = getelementptr inbounds %struct.IDispatchVtbl* %53, i32 0, i32 2
      %55 = load i32 (%struct.IDispatch*)** %54, align 4, !tbaa !0
      %56 = call x86_stdcallcc i32 %55(%struct.IDispatch* %51) nounwind
      call x86_stdcallcc void @CoUninitialize() nounwind
      ret i32 0
    }
     
    declare void @llvm.memset.p0i8.i32(i8* nocapture, i8, i32, i32, i1) nounwind
     
    declare x86_stdcallcc i32 @CoInitialize(i8*)
     
    declare x86_stdcallcc i32 @CLSIDFromProgID(i16*, %struct._GUID*)
     
    declare x86_stdcallcc i32 @CoCreateInstance(%struct._GUID*, %struct.IUnknown*, i32, %struct._GUID*, i8**)
     
    declare x86_stdcallcc i32 @GetUserDefaultLCID()
     
    declare x86_stdcallcc void @VariantInit(%struct.tagVARIANT*)
     
    declare x86_stdcallcc i16* @SysAllocString(i16*)
     
    declare x86_stdcallcc void @CoUninitialize()
     
    !0 = metadata !{metadata !"any pointer", metadata !1}
    !1 = metadata !{metadata !"omnipotent char", metadata !2}
    !2 = metadata !{metadata !"Simple C/C++ TBAA"}
    !3 = metadata !{metadata !"short", metadata !1}
    !4 = metadata !{metadata !"long", metadata !1}
    !5 = metadata !{metadata !"int", metadata !1}

    上記コードは以下のC言語のソースを clang でアセンブリコード出力(clang -S -O4 hello.c)したものに相当する。

    #include <ole2.h>
     
    int main( int argc, char* argv[] )
    {
        CLSID clsid;
        IDispatch* pShell;
        IDispatch* pFolder;
        DISPID dispid;
        OLECHAR* ptName = L"BrowseForFolder";
        DISPPARAMS param = { NULL, NULL, 0, 0 };
        VARIANT varg[4];
        VARIANT vResult;
     
        CoInitialize( NULL );
     
        CLSIDFromProgID(L"Shell.Application", &clsid );
        CoCreateInstance( &clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IDispatch, (void**)&pShell);
        pShell->lpVtbl->GetIDsOfNames( (void*)pShell, &IID_NULL, &ptName, 1, GetUserDefaultLCID(), &dispid );
     
        VariantInit( &varg[0] );
        varg[0].vt = VT_I4;
        varg[0].lVal = 36L;  /* ssfWINDOWS */
     
        VariantInit( &varg[1] );
        varg[1].vt = VT_I4;
        varg[1].lVal = 0L;
     
        VariantInit( &varg[2] );
        varg[2].vt = VT_BSTR;
        varg[2].bstrVal = SysAllocString(L"Hello, COM World!"); 
     
        VariantInit( &varg[3] );
        varg[3].vt = VT_I4;
        varg[3].lVal = 0L;
     
        param.cArgs = 4;
        param.rgvarg = varg;
     
        pShell->lpVtbl->Invoke( (void*)pShell, dispid, &IID_NULL, GetUserDefaultLCID(), DISPATCH_METHOD, &param, &vResult, NULL, NULL );
     
        VariantInit( &varg[0] );
        VariantInit( &varg[1] );
        VariantInit( &varg[2] );
        VariantInit( &varg[3] );
     
        pFolder = V_DISPATCH( &vResult );
        if ( pFolder != NULL )
        {
            pFolder->lpVtbl->Release( (void*)pFolder );
        }
        pShell->lpVtbl->Release( (void*)pShell );
     
        CoUninitialize();
     
        return 0;
    }

    コンパイル&リンク方法

    C:¥> clang -o hello hello.ll -l ole32  -l oleaut32 -l uuid

    実行結果

    +----------------------------------------+
    |Browse For Folder                    [X]|
    +----------------------------------------+
    | Hello, COM Wolrd!                      |
    |                                        |
    | +------------------------------------+ |
    | |[Windows]                           | |
    | | +[addins]                          | |
    | | +[AppCompat]                       | |
    | | +[AppPatch]                        | |
    | | +[assembly]                        | |
    | |     :                              | |
    | |     :                              | |
    | |     :                              | |
    | +------------------------------------+ |
    | [Make New Folder]    [  OK  ] [Cancel] |
    +----------------------------------------+
  3. Hello, Win32 API(GAS) World!

    Posted on 3月 14th, 2013 by cx20

    Win32 API(GAS)

    Win32 API は、Windows の機能にアクセスする為の API(Application Programming Interface)である。
    以下は GAS からの呼出し例である。

    ソースコード(GAS)

            .file   "hello.c"
            .def    ___main;        .scl    2;      .type   32;     .endef
            .section .rdata,"dr"
    LC0:
            .ascii "Hello, World!

    上記コードは、下記の C のソースを MinGW版 GCC にてアセンブリコード出力(gcc -S hello.c)したものである。

    ソースコード(C言語)

    #include <windows.h>
     
    int main( int argc, char* argv[] )
    {
        MessageBox( NULL, "Hello, Win32 API World!", "Hello, World!", MB_OK );
        return 0;
    }

    コンパイル方法(MinGW版 gcc)

    C:¥> gcc -c hello.s
    C:¥> gcc -o hello hello.o

    実行結果

    ---------------------------
    Hello, World!
    ---------------------------
    Hello, Win32 API World!
    ---------------------------
    OK   
    ---------------------------
  4. Hello, Win32 API(LLVM) World!

    Posted on 3月 13th, 2013 by cx20

    Win32 API(LLVM)

    Win32 API は、Windows の機能にアクセスする為の API(Application Programming Interface)である。
    以下は LLVM Assembler による呼出し例である。

    ソースコード(LLVM)

    ; ModuleID = 'hello.c'
    target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-f80:128:128-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32-S32"
    target triple = "i686-w64-mingw32"
     
    %struct.HWND__ = type { i32 }
     
    @.str = private unnamed_addr constant [24 x i8] c"Hello, Win32 API World!

    上記コードは、下記の C のソースを clang にてアセンブリコード出力(clang -S -O4 hello.c)したものである。

    ソースコード(C言語)

    #include <windows.h>
     
    int main( int argc, char* argv[] )
    {
        MessageBox( NULL, "Hello, Win32 API World!", "Hello, World!", MB_OK );
        return 0;
    }

    コンパイル方法(MinGW版 clang)

    C:¥> clang -o hello hello.ll

    実行結果

    ---------------------------
    Hello, World!
    ---------------------------
    Hello, Win32 API World!
    ---------------------------
    OK   
    ---------------------------
  5. Hello, Win32 GUI(MASM) World!

    Posted on 7月 6th, 2012 by cx20

    Win32 GUI(MASM)

    Win32 アプリケーションは Windows 標準 API である Win32 API を使用した Windows アプリケーションである。
    以下は MASM における Win32 GUI アプリケーション の例となっている。

    ソースコード

    ; Listing generated by Microsoft (R) Optimizing Compiler Version 16.00.40219.01 
     
            TITLE   hello.c
            .686P
            .XMM
            include listing.inc
            .model  flat
     
    INCLUDELIB LIBCMT
    INCLUDELIB OLDNAMES
     
    _DATA   SEGMENT
    $SG79977 DB     'Hello, Win32 GUI(MASM) World!', 00H
            ORG $+2
    $SG79995 DB     'helloWindow', 00H
    $SG79997 DB     'Hello, World!', 00H
    _DATA   ENDS
    PUBLIC  __$ArrayPad$
    PUBLIC  _WndProc@16
    EXTRN   __imp__DefWindowProcA@16:PROC
    EXTRN   __imp__PostQuitMessage@4:PROC
    EXTRN   __imp__EndPaint@8:PROC
    EXTRN   __imp__TextOutA@20:PROC
    EXTRN   __imp__lstrlenA@4:PROC
    EXTRN   __imp__BeginPaint@8:PROC
    EXTRN   ___security_cookie:DWORD
    EXTRN   @__security_check_cookie@4:PROC
    ; Function compile flags: /Odtp
    _TEXT   SEGMENT
    tv64 = -84                                              ; size = 4
    _hdc$ = -80                                             ; size = 4
    _lpszMessage$ = -76                                     ; size = 4
    _ps$ = -72                                              ; size = 64
    __$ArrayPad$ = -4                                       ; size = 4
    _hWnd$ = 8                                              ; size = 4
    _message$ = 12                                          ; size = 4
    _wParam$ = 16                                           ; size = 4
    _lParam$ = 20                                           ; size = 4
    _WndProc@16 PROC
    ; File hello.c
    ; Line 5
            push    ebp
            mov     ebp, esp
            sub     esp, 84                                 ; 00000054H
            mov     eax, DWORD PTR ___security_cookie
            xor     eax, ebp
            mov     DWORD PTR __$ArrayPad$[ebp], eax
    ; Line 8
            mov     DWORD PTR _lpszMessage$[ebp], OFFSET $SG79977
    ; Line 10
            mov     eax, DWORD PTR _message$[ebp]
            mov     DWORD PTR tv64[ebp], eax
            cmp     DWORD PTR tv64[ebp], 2
            je      SHORT $LN2@WndProc
            cmp     DWORD PTR tv64[ebp], 15                 ; 0000000fH
            je      SHORT $LN3@WndProc
            jmp     SHORT $LN1@WndProc
    $LN3@WndProc:
    ; Line 13
            lea     ecx, DWORD PTR _ps$[ebp]
            push    ecx
            mov     edx, DWORD PTR _hWnd$[ebp]
            push    edx
            call    DWORD PTR __imp__BeginPaint@8
            mov     DWORD PTR _hdc$[ebp], eax
    ; Line 14
            mov     eax, DWORD PTR _lpszMessage$[ebp]
            push    eax
            call    DWORD PTR __imp__lstrlenA@4
            push    eax
            mov     ecx, DWORD PTR _lpszMessage$[ebp]
            push    ecx
            push    0
            push    0
            mov     edx, DWORD PTR _hdc$[ebp]
            push    edx
            call    DWORD PTR __imp__TextOutA@20
    ; Line 15
            lea     eax, DWORD PTR _ps$[ebp]
            push    eax
            mov     ecx, DWORD PTR _hWnd$[ebp]
            push    ecx
            call    DWORD PTR __imp__EndPaint@8
    ; Line 16
            jmp     SHORT $LN4@WndProc
    $LN2@WndProc:
    ; Line 18
            push    0
            call    DWORD PTR __imp__PostQuitMessage@4
    ; Line 19
            jmp     SHORT $LN4@WndProc
    $LN1@WndProc:
    ; Line 21
            mov     edx, DWORD PTR _lParam$[ebp]
            push    edx
            mov     eax, DWORD PTR _wParam$[ebp]
            push    eax
            mov     ecx, DWORD PTR _message$[ebp]
            push    ecx
            mov     edx, DWORD PTR _hWnd$[ebp]
            push    edx
            call    DWORD PTR __imp__DefWindowProcA@16
            jmp     SHORT $LN6@WndProc
    $LN4@WndProc:
    ; Line 25
            xor     eax, eax
    $LN6@WndProc:
    ; Line 26
            mov     ecx, DWORD PTR __$ArrayPad$[ebp]
            xor     ecx, ebp
            call    @__security_check_cookie@4
            mov     esp, ebp
            pop     ebp
            ret     16                                      ; 00000010H
    _WndProc@16 ENDP
    _TEXT   ENDS
    PUBLIC  _WinMain@16
    EXTRN   __imp__DispatchMessageA@4:PROC
    EXTRN   __imp__TranslateMessage@4:PROC
    EXTRN   __imp__GetMessageA@16:PROC
    EXTRN   __imp__UpdateWindow@4:PROC
    EXTRN   __imp__ShowWindow@8:PROC
    EXTRN   __imp__CreateWindowExA@48:PROC
    EXTRN   __imp__RegisterClassExA@4:PROC
    EXTRN   __imp__LoadCursorA@8:PROC
    EXTRN   __imp__LoadIconA@8:PROC
    ; Function compile flags: /Odtp
    _TEXT   SEGMENT
    _lpszClassName$ = -88                                   ; size = 4
    _msg$ = -84                                             ; size = 28
    _wcex$ = -56                                            ; size = 48
    _hWnd$ = -8                                             ; size = 4
    _lpszWindowName$ = -4                                   ; size = 4
    _hInstance$ = 8                                         ; size = 4
    _hPrevInstance$ = 12                                    ; size = 4
    _lpCmdLine$ = 16                                        ; size = 4
    _nCmdShow$ = 20                                         ; size = 4
    _WinMain@16 PROC
    ; Line 29
            push    ebp
            mov     ebp, esp
            sub     esp, 88                                 ; 00000058H
    ; Line 30
            mov     DWORD PTR _lpszClassName$[ebp], OFFSET $SG79995
    ; Line 31
            mov     DWORD PTR _lpszWindowName$[ebp], OFFSET $SG79997
    ; Line 36
            mov     DWORD PTR _wcex$[ebp], 48               ; 00000030H
    ; Line 37
            mov     DWORD PTR _wcex$[ebp+4], 3
    ; Line 38
            mov     DWORD PTR _wcex$[ebp+8], OFFSET _WndProc@16
    ; Line 39
            mov     DWORD PTR _wcex$[ebp+12], 0
    ; Line 40
            mov     DWORD PTR _wcex$[ebp+16], 0
    ; Line 41
            mov     eax, DWORD PTR _hInstance$[ebp]
            mov     DWORD PTR _wcex$[ebp+20], eax
    ; Line 42
            push    32512                                   ; 00007f00H
            mov     ecx, DWORD PTR _hInstance$[ebp]
            push    ecx
            call    DWORD PTR __imp__LoadIconA@8
            mov     DWORD PTR _wcex$[ebp+24], eax
    ; Line 43
            push    32512                                   ; 00007f00H
            push    0
            call    DWORD PTR __imp__LoadCursorA@8
            mov     DWORD PTR _wcex$[ebp+28], eax
    ; Line 44
            mov     DWORD PTR _wcex$[ebp+32], 6
    ; Line 45
            mov     DWORD PTR _wcex$[ebp+36], 0
    ; Line 46
            mov     edx, DWORD PTR _lpszClassName$[ebp]
            mov     DWORD PTR _wcex$[ebp+40], edx
    ; Line 47
            push    32512                                   ; 00007f00H
            mov     eax, DWORD PTR _wcex$[ebp+20]
            push    eax
            call    DWORD PTR __imp__LoadIconA@8
            mov     DWORD PTR _wcex$[ebp+44], eax
    ; Line 49
            lea     ecx, DWORD PTR _wcex$[ebp]
            push    ecx
            call    DWORD PTR __imp__RegisterClassExA@4
    ; Line 56
            push    0
            mov     edx, DWORD PTR _hInstance$[ebp]
            push    edx
            push    0
            push    0
            push    480                                     ; 000001e0H
            push    640                                     ; 00000280H
            push    -2147483648                             ; 80000000H
            push    -2147483648                             ; 80000000H
            push    13565952                                ; 00cf0000H
            mov     eax, DWORD PTR _lpszWindowName$[ebp]
            push    eax
            mov     ecx, DWORD PTR _lpszClassName$[ebp]
            push    ecx
            push    0
            call    DWORD PTR __imp__CreateWindowExA@48
            mov     DWORD PTR _hWnd$[ebp], eax
    ; Line 58
            push    10                                      ; 0000000aH
            mov     edx, DWORD PTR _hWnd$[ebp]
            push    edx
            call    DWORD PTR __imp__ShowWindow@8
    ; Line 59
            mov     eax, DWORD PTR _hWnd$[ebp]
            push    eax
            call    DWORD PTR __imp__UpdateWindow@4
    $LN2@WinMain:
    ; Line 61
            push    0
            push    0
            push    0
            lea     ecx, DWORD PTR _msg$[ebp]
            push    ecx
            call    DWORD PTR __imp__GetMessageA@16
            test    eax, eax
            je      SHORT $LN1@WinMain
    ; Line 63
            lea     edx, DWORD PTR _msg$[ebp]
            push    edx
            call    DWORD PTR __imp__TranslateMessage@4
    ; Line 64
            lea     eax, DWORD PTR _msg$[ebp]
            push    eax
            call    DWORD PTR __imp__DispatchMessageA@4
    ; Line 65
            jmp     SHORT $LN2@WinMain
    $LN1@WinMain:
    ; Line 67
            mov     eax, DWORD PTR _msg$[ebp+8]
    ; Line 68
            mov     esp, ebp
            pop     ebp
            ret     16                                      ; 00000010H
    _WinMain@16 ENDP
    _TEXT   ENDS
    END

    上記コードは以下のC言語のソースを VC++ でアセンブリコード出力(cl /FA hello.c)したものに相当する。

    #include <windows.h>
    #include <tchar.h>
     
    LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        PAINTSTRUCT ps;
        HDC hdc;
        LPCTSTR lpszMessage = _T("Hello, Win32 GUI(MASM) World!");
     
        switch (message)
        {
        case WM_PAINT:
            hdc = BeginPaint( hWnd, &ps );
            TextOut( hdc, 0, 0, lpszMessage, lstrlen(lpszMessage) );
            EndPaint( hWnd, &ps );
            break;
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
            break;
        }
     
        return 0;
    }
     
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
    {
        LPCTSTR lpszClassName = _T("helloWindow");
        LPCTSTR lpszWindowName = _T("Hello, World!");
        WNDCLASSEX wcex;
        HWND hWnd;
        MSG msg;
     
        wcex.cbSize = sizeof(WNDCLASSEX);
        wcex.style          = CS_HREDRAW | CS_VREDRAW;
        wcex.lpfnWndProc    = WndProc;
        wcex.cbClsExtra     = 0;
        wcex.cbWndExtra     = 0;
        wcex.hInstance      = hInstance;
        wcex.hIcon          = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
        wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
        wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
        wcex.lpszMenuName   = NULL;
        wcex.lpszClassName  = lpszClassName;
        wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
     
        RegisterClassEx(&wcex);
        hWnd = CreateWindow(
            lpszClassName,
            lpszWindowName,
            WS_OVERLAPPEDWINDOW,
            CW_USEDEFAULT, CW_USEDEFAULT, 640, 480,
            NULL, NULL, hInstance, NULL
        );
     
        ShowWindow(hWnd, SW_SHOWDEFAULT);
        UpdateWindow(hWnd);
     
        while (GetMessage(&msg, NULL, 0, 0))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
     
        return (int)msg.wParam;
    }

    コンパイル方法

    C:¥> ml hello.asm /link user32.lib gdi32.lib /SUBSYSTEM:WINDOWS

    実行結果

    +------------------------------------------+
    |Hello, World!                    [_][~][X]|
    +------------------------------------------+
    |Hello, Win32 GUI(MASM) World!             |
    |                                          |
    |                                          |
    |                                          |
    |                                          |
    |                                          |
    |                                          |
    |                                          |
    |                                          |
    |                                          |
    +------------------------------------------+
  6. Hello, COM(MASM) World!

    Posted on 5月 12th, 2012 by cx20

    COM(MASM)

    COM(Component Object Model)はマイクロソフトの提唱するプログラム部品の仕様である。
    COM を用いて開発された部品であれば言語を問わず利用することができる。
    以下は MASM による COM クライアントの例となっている。

    ソースコード

    ; Listing generated by Microsoft (R) Optimizing Compiler Version 16.00.40219.01 
     
    	TITLE	hello.c
    	.686P
    	.XMM
    	include listing.inc
    	.model	flat
     
    INCLUDELIB LIBCMT
    INCLUDELIB OLDNAMES
     
    _DATA	SEGMENT
    $SG113507 DB	'H', 00H, 'e', 00H, 'l', 00H, 'l', 00H, 'o', 00H, ',', 00H
    	DB	' ', 00H, 'C', 00H, 'O', 00H, 'M', 00H, '(', 00H, 'M', 00H, 'A'
    	DB	00H, 'S', 00H, 'M', 00H, ')', 00H, ' ', 00H, 'W', 00H, 'o', 00H
    	DB	'r', 00H, 'l', 00H, 'd', 00H, '!', 00H, 00H, 00H
    _DATA	ENDS
    PUBLIC	_main
    EXTRN	__imp__CoUninitialize@0:PROC
    EXTRN	__imp__CoCreateInstance@20:PROC
    EXTRN	_CLSID_Shell:BYTE
    EXTRN	_IID_IShellDispatch:BYTE
    EXTRN	__imp__CoInitialize@4:PROC
    ; Function compile flags: /Odtp
    _TEXT	SEGMENT
    _pFolder$ = -36						; size = 4
    _vRootFolder$ = -32					; size = 16
    _folder$ = -12						; size = 4
    _pShell$ = -4						; size = 4
    _argc$ = 8						; size = 4
    _argv$ = 12						; size = 4
    _main	PROC
    ; File hello.c
    ; Line 4
            push    ebp
            mov     ebp, esp
            sub     esp, 36                                 ; 00000024H
    ; Line 11
            push    0
            call    DWORD PTR __imp__CoInitialize@4
    ; Line 13
            lea     eax, DWORD PTR _pShell$[ebp]
            push    eax
            push    OFFSET _IID_IShellDispatch
            push    1
            push    0
            push    OFFSET _CLSID_Shell
            call    DWORD PTR __imp__CoCreateInstance@20
    ; Line 15
            mov     ecx, 3
            mov     WORD PTR _vRootFolder$[ebp], cx
    ; Line 16
            mov     DWORD PTR _vRootFolder$[ebp+8], 36      ; 00000024H
    ; Line 17
            lea     edx, DWORD PTR _folder$[ebp]
            mov     DWORD PTR _pFolder$[ebp], edx
    ; Line 19
            lea     eax, DWORD PTR _pFolder$[ebp]
            push    eax
            sub     esp, 16                                 ; 00000010H
            mov     ecx, esp
            mov     edx, DWORD PTR _vRootFolder$[ebp]
            mov     DWORD PTR [ecx], edx
            mov     eax, DWORD PTR _vRootFolder$[ebp+4]
            mov     DWORD PTR [ecx+4], eax
            mov     edx, DWORD PTR _vRootFolder$[ebp+8]
            mov     DWORD PTR [ecx+8], edx
            mov     eax, DWORD PTR _vRootFolder$[ebp+12]
            mov     DWORD PTR [ecx+12], eax
            push    0
            push    OFFSET $SG113507
            push    0
            mov     ecx, DWORD PTR _pShell$[ebp]
            push    ecx
            mov     edx, DWORD PTR _pShell$[ebp]
            mov     eax, DWORD PTR [edx]
            mov     ecx, DWORD PTR [eax+40]
            call    ecx
    ; Line 20
            cmp     DWORD PTR _pFolder$[ebp], 0
            je      SHORT $LN1@main
    ; Line 22
            mov     edx, DWORD PTR _pFolder$[ebp]
            push    edx
            mov     eax, DWORD PTR _pFolder$[ebp]
            mov     ecx, DWORD PTR [eax]
            mov     edx, DWORD PTR [ecx+8]
            call    edx
    $LN1@main:
    ; Line 24
            mov     eax, DWORD PTR _pShell$[ebp]
            push    eax
            mov     ecx, DWORD PTR _pShell$[ebp]
            mov     edx, DWORD PTR [ecx]
            mov     eax, DWORD PTR [edx+8]
            call    eax
    ; Line 26
            call    DWORD PTR __imp__CoUninitialize@0
    ; Line 28
            xor     eax, eax
    ; Line 29
            mov     esp, ebp
            pop     ebp
            ret     0
    _main   ENDP
    _TEXT   ENDS
    END

    上記コードは以下のC言語のソースを VC++ でアセンブリコード出力(cl /FA hello.c)したものに相当する。

    #include <shlobj.h>
     
    int main( int argc, char* argv[] )
    {
        HRESULT hResult;
        IShellDispatch* pShell;
        VARIANT vRootFolder;
        Folder* pFolder;
     
        CoInitialize( NULL );
     
        CoCreateInstance( &CLSID_Shell, NULL, CLSCTX_INPROC_SERVER, &IID_IShellDispatch, (void**)&pShell );
     
        VariantInit( &vRootFolder );
        vRootFolder.vt = VT_I4;
        vRootFolder.lVal = ssfWINDOWS;
     
        pShell->lpVtbl->BrowseForFolder( (void*)pShell, 0, L"Hello, COM(MASM) World!", 0, vRootFolder, &pFolder );
        VariantClear( &vRootFolder );
        if ( pFolder != NULL )
        {
            pFolder->lpVtbl->Release( (void*)pFolder );
        }
        pShell->lpVtbl->Release( (void*)pShell );
     
        CoUninitialize();
     
        return 0;
    }

    コンパイル&リンク方法

    C:¥> ml -c hello.asm
    C:¥> midl shldisp.idl
    C:¥> cl shldisp_i.c
    C:¥> link hello.obj shldisp_i.obj ole32.lib oleaut32.lib

    実行結果

    +----------------------------------------+
    |Browse For Folder                    [X]|
    +----------------------------------------+
    | Hello, COM(MASM) Wolrd!                |
    |                                        |
    | +------------------------------------+ |
    | |[Windows]                           | |
    | | +[addins]                          | |
    | | +[AppCompat]                       | |
    | | +[AppPatch]                        | |
    | | +[assembly]                        | |
    | |     :                              | |
    | |     :                              | |
    | |     :                              | |
    | +------------------------------------+ |
    | [Make New Folder]    [  OK  ] [Cancel] |
    +----------------------------------------+
  7. Hello, Win32 API(MASM) World!

    Posted on 4月 17th, 2012 by cx20

    Win32 API(MASM)

    Win32 API は、Windows の機能にアクセスする為の API(Application Programming Interface)である。
    以下は MASM からの呼出し例である。

    ソースコード(MASM)

    ; Listing generated by Microsoft (R) Optimizing Compiler Version 14.00.50727.762 
     
            TITLE   hello.c
            .686P
            .XMM
            include listing.inc
            .model  flat
     
    INCLUDELIB LIBCMT
    INCLUDELIB OLDNAMES
     
    _DATA   SEGMENT
    $SG77810 DB     'Hello, World!', 00H
            ORG $+2
    $SG77811 DB     'Hello, Win32 API(MASM) World!', 00H
    _DATA   ENDS
    PUBLIC  _main
    EXTRN   __imp__MessageBoxA@16:PROC
    ; Function compile flags: /Odtp
    _TEXT   SEGMENT
    _argc$ = 8                                              ; size = 4
    _argv$ = 12                                             ; size = 4
    _main   PROC
    ; File hello.c
    ; Line 4
            push    ebp
            mov     ebp, esp
    ; Line 5
            push    0
            push    OFFSET $SG77810
            push    OFFSET $SG77811
            push    0
            call    DWORD PTR __imp__MessageBoxA@16
    ; Line 6
            xor     eax, eax
    ; Line 7
            pop     ebp
            ret     0
    _main   ENDP
    _TEXT   ENDS
    END

    上記コードは、下記の C のソースを「cl hello.c /FA」にてアセンブラ出力したものである。

    ソースコード(C言語)

    #include <windows.h>
     
    int main( int argc, char* argv[] )
    {
        MessageBoxA( NULL, "Hello, Win32 API(MASM) World!", "Hello, World!", MB_OK );
        return 0;
    }

    コンパイル方法(Visual C++)

    C:¥> ml hello.asm
    C:¥> link hello.obj user32.lib

    実行結果

    ---------------------------
    Hello, World!
    ---------------------------
    Hello, Win32 API(MASM) World!
    ---------------------------
    OK   
    ---------------------------
  8. Hello, Java VM Assembler World!

    Posted on 1月 6th, 2012 by cx20

    Java VM Assembler

    Java VM アセンブラは Java VM の中間コード(バイトコード)を生成するアセンブラである。
    主要な Java VM アセンブラとしては、Jasmin 等がある。

    ソースコード

    .class public Hello
    .super java/lang/Object
     
    .method public ()V
       aload_0
       invokespecial java/lang/Object/()V
       return
    .end method
     
    .method public static main([Ljava/lang/String;)V
       .limit stack 2
       getstatic java/lang/System/out Ljava/io/PrintStream;
       ldc "Hello, Java VM World!"
       invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V
       return
    .end method

    上記コードは以下の Java のソースに対応する。
    クラスファイルを tinapoc と言った逆アセンブラや javap で逆アセンブル(javap -c Hello)することでアセンブリコードを得られる。

    public class Hello {
        public static void main( String[] args ) {
            System.out.println( "Hello, Java VM World!" );
        }
    }

    コンパイル&実行方法(Jasmin)

    $ java -jar jasmin.jar Hello.j
    $ java Hello

    実行結果

    Hello, Java VM World!
  9. Hello, CASL World!

    Posted on 1月 5th, 2012 by cx20

    CASL

    CASL は情報処理技術者試験の為に仕様策定されたアセンブリ言語である。仮想計算機 COMET 上で動作する。
    2001年より仕様改訂され現在は COMMET II / CASL II が利用されている。

    ソースコード

    MAIN    START
            OUT     MSG,LEN
            RET
    MSG     DC      'Hello, CASL World!'
    LEN     DC      18
            END

    コンパイル&実行方法(YACASL2)

    $ casl2 -Ohello.o hello.cas
    $ comet2 hello.o
    

    コンパイル&実行(JPA CASL II シミュレータ)

    $ java -jar casl2.jar hello.cas
    $ java -jar run.jar hello.obj
    

    実行結果

    Hello, CASL World!
    
  10. Hello, MASM World!

    Posted on 1月 4th, 2012 by cx20

    MASM

    MASM はマイクロソフト社製のアセンブリ言語である。正式名称は Microsoft Macro Assembler。Visual C++ に付属している。

    ソースコード(32bit版)

    .MODEL flat
    EXTRN   _printf:PROC
     
    _DATA   SEGMENT
    msg     DB      'Hello, MASM World!', 0aH, 00H
    _DATA   ENDS
     
    _TEXT   SEGMENT
    _main   PROC
            push    OFFSET msg
            call    _printf
            add     esp, 4
            xor     eax, eax
            ret     0
    _main   ENDP
    _TEXT   ENDS
    END

    ソースコード(64bit版)

    EXTRN   printf:PROC
     
    _DATA   SEGMENT
    msg     DB      'Hello, MASM World!', 0aH, 00H
    _DATA   ENDS
     
    _TEXT   SEGMENT
    main    PROC
            sub     rsp, 40
            lea     rcx, OFFSET msg
            call    printf
            xor     rax, rax
            add     rsp, 40
            ret     0
    main    ENDP
    _TEXT   ENDS
    END

    上記コードは以下のC言語のソースを VC++ でアセンブリコード出力(cl /FA hello.c)したものに相当する。

    #include <stdio.h>
     
    int main( int argc, char* argv[] )
    {
        printf( "Hello, MASM World!n" );
        return 0;
    }

    コンパイル&リンク方法(MASM 32bit版)

    C:¥> ml -c hello.asm
    C:¥> link hello.obj libcmt.lib

    コンパイル&リンク方法(MASM 64bit版)

    C:¥> ml64 -c hello64.asm
    C:¥> link hello64.obj libcmt.lib

    実行結果

    Hello, MASM World!