Lotus Script: взгляд изнутри

Тема в разделе "Lotus - Программирование", создана пользователем Yakov, 9 июл 2009.

  1. Yakov

    Yakov Гость

    Здравствуйте, уважаемые разработчики.

    Краткая заметка о виртуальной машине LS и системе ее команд находится во вложении.
    А здесь мы рассмотрим некоторые примеры.

    Преобразования типов и встроенные функции
    Встроенные функции, возвращающие строки, (Chr, Ucase, Lcase и другие) в зависимости от написания (Chr или Chr$) возвращают либо Variant of DataType 8 (String), либо String.
    Посмотрим, как это выглядит "внутри".
    Код (Text):
    Dim s As String
    s = Chr(13)
    s = Chr$(13)
    После трансляции:
    Код (Text):
        Dim S As String
    line #
    lvalue_l S
    push_long 13
    Chr
    Cvar
    Cstr
    Let
    line #
    lvalue_l S
    push_long 13
    Chr
    Cstr
    Let
    В первом присвоении выполняется лишнее преобразование типов, чего можно избежать, используя "$" в имени функции.

    Select Case
    Код
    Код (Text):
    Public Sub printNumber(x As Integer)
    Select Case x
    Case 0: Print "zero"
    Case 1: Print "one"
    Case Else: Print "something else"
    End Select
    End Sub
    транслируется в
    Код (Text):
    Public Sub PRINTNUMBER(X As Integer)
    line # 13
    line #
    goto label_3
    label_0:
    line # 14
    stack_copy
    push_int_0
    =
    if_false_goto label_1
    pop
    line #
    push_str_const {zero}
    Print
    line #
    goto label_4
    label_1:
    line # 15
    stack_copy
    push_int_1
    =
    if_false_goto label_2
    pop
    line #
    push_str_const {one}
    Print
    line #
    goto label_4
    label_2:
    pop
    line # 16
    push_str_const {something else}
    Print
    line #
    goto label_4
    label_3:
    line #
    rvalue_pi X
    goto label_0
    label_4:
    line # 18
    end_routine
    End Sub
    Что здесь происходит. Переменная x сравнивается с каждым из значений в операторе Select Case последовательно. Если есть совпадение, выполянется соответствующий код и происходит переход на следующую за End Select строчку. Таким образом, если в вашем коде одна из веток Case ... встречается чаще других, ее следует поставить на первое место.

    Вычисление булевых значений (операторы And, Or)
    Некоторые компиляторы языков высокого уровня допускают частичное вычисление булевых значений: вычисление прекращается, как только будет известно его значение. К примеру, значение выражения False And x = 0 известро еще до вычисления значения x = 0, оно равно False. Компилятор языка Lotus Script всегда выполняет полное вычисление булевых значений, поэтому в LS невозможна проверка вида
    Код (Text):
    If Not document Is Nothing And document.Created > cutOff Then
    ...
    End If
    Код (Text):
        rvalue_p DOCUMENT
    push_Nothing
    Is
    Not
    rvalue_object DOCUMENT
    push_property CREATED
    call_routine
    rvalue_p CUTOFF
    >=
    And
    if_false_goto label_0
    ...
    label_0:
    Если все таки document Is Nothing, то вычисление document.Created вызовет ошибку.

    Переменного числа аргументов не существует
    Компилятор подставляет пропущенные значения.
    Код (Text):
    Print Instr(x, "a")
    транслируется в
    Код (Text):
        push_1
    rvalue_l X
    push_str_const {b}
    push_int 0
    Instr
    Print
    Код (Text):
    Dim uiWorkspace As New NotesUIWorkspace()
    Call uiWorkspace.Prompt(PROMPT_OK, "Test", "OK")
    транслируется в
    Код (Text):
    line #
    lvalue_l UIWORKSPACE
    push_constructor NOTESUIWORKSPACE
    сall_constructor
    Set
    line #
    rvalue_object UIWORKSPACE
    push_routine PROMPT
    push_num_const PROMPT_OK = 1
    push_str_const {Test}
    push_str_const {OK}
    push_int 0
    push_int 0
    call_routine
    pop
    Расширенный синтаксис
    Пришло время поставить все точки над ё в вопросе о расширенном синтаксисе. Сравним:
    Код (Text):
        Print document.GetItemValue("Form")(0)
    Print document.Form(0)

    Call document.ReplaceItemValue("Form", "test")
    document.Form = "test"
    и
    Код (Text):
    line #
    rvalue_object DOCUMENT
    push_lsx_routine GETITEMVALUE
    push_str_const {Form}
    call_routine
    push_int_0
    rvalue_arr
    Print

    line #
    rvalue_object DOCUMENT
    push_notes_function FORM
    push_int_0
    call_notes_function
    Print

    line #
    rvalue_object DOCUMENT
    push_lsx_routine REPLACEITEMVALUE
    push_str_const {Form}
    push_str_const {test}
    call_routine
    pop

    line #
    rvalue_object DOCUMENT
    lvalue_document_field FORM
    push_str_const {test}
    Let

    А теперь переходим к части, обозначенной подзаголовком. Ваши вопросы, господа и дамы.
     

    Вложения:

  2. Omh

    Omh Lotus team
    Lotus team

    Регистрация:
    4 июл 2007
    Сообщения:
    2.210
    Симпатии:
    0
    Yakov, однако ты очень крут!
     
  3. ToxaRat

    ToxaRat Чёрный маг
    Lotus team

    Регистрация:
    6 ноя 2007
    Сообщения:
    3.047
    Симпатии:
    18
    так а чего коментов по расширенному синтаксису нету? ;)

    и почему не указано чем производилось дизассемблирование?
    я вот сейчас как раз пишу анализатор LS - выложу потому всем кому интересно будет
    поэтому мне было бы более интересно если бы статья приобрела более расширенный вид
     
  4. Akupaka

    Akupaka А че я?.. О.о

    Регистрация:
    4 окт 2007
    Сообщения:
    3.373
    Симпатии:
    2
    так, а как на счет точек-то? )
    мы видим лишь, что выполняются разные макросы, но это ни на что не указывает ;)
    фактически, мы не знаем, что происходит на самом деле...

    или я чего-то не понял? :)
     
  5. Omh

    Omh Lotus team
    Lotus team

    Регистрация:
    4 июл 2007
    Сообщения:
    2.210
    Симпатии:
    0
    Akupaka, ты не одинок ;)
     
  6. Yakov

    Yakov Гость

    ToxaRat, дизассемблирование производилось "в уме". ;) То есть самописной тулзой. Какое расширение статьи вы хотите увидеть? Задавайте вопросы, я постараюсь на них ответить.
    Akupaka, мы видим, что выполняемый код - разный. И можно лишь говорить о том, что компилируется эквивалентный код в смысле получаемых результатов, но не одинаковый.
    Рассмотрим подробнее, что делает ВМ в обоих случаях. Хочу сразу предупредить, что как она это делает, я не знаю.
    Call document.ReplaceItemValue("Form", "test")
    В этом случае ВМ
    Код (Text):
        rvalue_object DOCUMENT ;кладет на стек данных объект DOCUMENT
    push_lsx_routine REPLACEITEMVALUE ;кладет на стек вызовов адрес функции NotesDocument.ReplaceItemValue; класс и его функция находятся в библиотеке nlsxbe.dll
    push_str_const {Form} ;кладет на стек данных строковую константу
    push_str_const {test} ;кладет на стек данных строковую константу
    call_routine ;вызывает функцию с вершины стека вызовов
    pop ;выталкивает со стека данных неиспользуемый результат функции
    Случай document.Form = "test":
    Код (Text):
        rvalue_object DOCUMENT ;кладет на стек объект DOCUMENT
    lvalue_document_field FORM ;кладет на стек адрес поля FORM
    push_str_const {test} ;кладет на стек строковую константу
    Let ;осуществляет присвоение значения переменной
    ВМ в разных случаях выполняет разные инструкции. Возможно, в итоге будет выполнена одна и та же последовательность вызовов функций Lotus API.
    Хочу также отметить, что я не являюсь противником расширенного синтаксиса, я лишь хочу показать, что это не одно и то же, а две большие разницы.
    Анонс. Через некоторое время (~полгода :-D) я покажу еще одно преимущество GetItemValue/ReplaceItemValue перед расширенным синтаксисом.
     
  7. Akupaka

    Akupaka А че я?.. О.о

    Регистрация:
    4 окт 2007
    Сообщения:
    3.373
    Симпатии:
    2
    можешь сказать, что вернет?
    set notesItem = document.ReplaceItemValue("Form", "test")

    самое интересно, что я противник расширенного синтаксиса ))
    "это не одно и то же, а две большие разницы" почему это? результат один, потому я и указал, что мы видим две последовательности макросов, но т.к. мы не знаем, что делают эти макросы на более низком уровне, то мы не можем быть уверенными, что это разные вещи :) (не для спора, просто имхо)
    кстати, не планируешь выложить какую-то тулзу, которая позволила бы эксперементировать с дизассемблированием? ;)
     
  8. Omh

    Omh Lotus team
    Lotus team

    Регистрация:
    4 июл 2007
    Сообщения:
    2.210
    Симпатии:
    0
    Akupaka, так выкладывал же...
    Которая приводила дамп к читабельному виду.

    Я так понимаю, она парсила именно это:
    Код (Text):
    Секция определений содержит описания всех используемых в библиотеке элементов
     
  9. Akupaka

    Akupaka А че я?.. О.о

    Регистрация:
    4 окт 2007
    Сообщения:
    3.373
    Симпатии:
    2
    та утилита делала то же самое, что тут в теме? я ж ее не смотрел ;)
     
  10. Yakov

    Yakov Гость

    Akupaka
    Код (Text):
    Public Sub TEST(DOCUMENT As NOTESDOCUMENT)
    Dim ITEM As NOTESITEM
    line # 13
    lvalue_l ITEM
    rvalue_object DOCUMENT
    push_lsx_routine REPLACEITEMVALUE
    push_str_const {Form}
    push_str_const {test}
    call_routine
    Set
    line # 14
    end_routine
    End Sub
    Тулзу выкладывать не собираюсь, потому что есть еше люди, которые пишут коммерческий код на LS и считающие его недекомпилируемым.

    Omh, ага, точно. Но там разбора секции кода не было.
     
  11. Akupaka

    Akupaka А че я?.. О.о

    Регистрация:
    4 окт 2007
    Сообщения:
    3.373
    Симпатии:
    2
    бедняжки ))
    ну, если желание появится, то мы всегда рады ;)
     
  12. Omh

    Omh Lotus team
    Lotus team

    Регистрация:
    4 июл 2007
    Сообщения:
    2.210
    Симпатии:
    0
    Yakov
    Погоди, ты хочешь сказать, что код таки декомпилируем?
    Как я понял, он не декомпилируется в тот вид, в котором пишем мы в Designer'e, но декомпилируется в вызовы ВМ, которые при определённой сноровке легко прочесть.
    Так?
     
  13. TIA

    TIA :-)
    Lotus team

    Регистрация:
    15 май 2009
    Сообщения:
    790
    Симпатии:
    0
    Почему-то мне кажется, что это ваш коммерческий код. Я не прав? ;)
     
  14. Omh

    Omh Lotus team
    Lotus team

    Регистрация:
    4 июл 2007
    Сообщения:
    2.210
    Симпатии:
    0
    Я полагаю, там юзаются апишные ф-ии.
    NSFFormulaDecompile может декопилить LS код?

    А вообще, новости довольно плохие ;)

    Может ещё найдётся способ из нотесного хеша получить обратно начальное значение?
     
  15. Yakov

    Yakov Гость

    Omh, так. Но декомпилятор из дизассемблера я пока делать не собираюсь.
    TIA, я пишу коммерческий код на LS. А код тулзы - он для интереса (образовательные цели и все такое, см. disclaimer).
     
  16. TIA

    TIA :-)
    Lotus team

    Регистрация:
    15 май 2009
    Сообщения:
    790
    Симпатии:
    0
    Конечно, как и любой другой декомпилятор/дизассемблер. Комментов они не расставят ;)
     
  17. Yakov

    Yakov Гость

    Omh
    Notes API используется для дампа бинарника библиотеки (ls-dump.exe). Код этой программы могу показать.
    NSFFormulaDecompile придется использовать для декомпиляции прекомпилированных формул для Evaluate.
    Все остальное - ручками и головой.
    А это о чем?
     
  18. Omh

    Omh Lotus team
    Lotus team

    Регистрация:
    4 июл 2007
    Сообщения:
    2.210
    Симпатии:
    0
    Yakov
    Ясно, круто.

    Насчёт хеша, это я к тому, что раньше был уверен, что скопиленный код недекомпилируем.
    Эта стенка рухнула.

    Второе, во что я верю, что из строки полученный команой HashPassword невозможно получить исходную строку.
    Надеюсь на то, что это всё таки истина ;)
     
  19. Yakov

    Yakov Гость

    Omh, это смотря какой криптографический хеш используется. Надо бы поэкспериментировать и поискать, какие хеши уже взломаны. ;)
     
  20. TIA

    TIA :-)
    Lotus team

    Регистрация:
    15 май 2009
    Сообщения:
    790
    Симпатии:
    0
    Ок. Ок. Просто опрометчиво было полагаться на декомпилируемось.

    А тулза, вроде как, показывала публичные декларации библиотек со скрытым кодом. Но декомпилированный псевдокод не показывала. Или это недокументированная фича?
     
Загрузка...

Поделиться этой страницей